提交 6390b951 authored 作者: lihuihui's avatar lihuihui

update

上级 186070ac
VITE_LOGIN_URL=https://login.ezijing.com/auth/login/index
VITE_LOGIN_URL=https://login.ezijing.com/highway/login/index
VITE_SHARE_URL=https://accounts.ezijing.com
VITE_LOGIN_URL=https://login.ezijing.com/auth/login/index
VITE_LOGIN_URL=https://login.ezijing.com/highway/login/index
VITE_SHARE_URL=https://accounts.ezijing.com
VITE_LOGIN_URL=https://login.ezijing.com/auth/login/index
VITE_LOGIN_URL=https://login.ezijing.com/highway/login/index
VITE_SHARE_URL=https://accounts.ezijing.com
......@@ -6,7 +6,9 @@ module.exports = {
rules: {
'vue/no-mutating-props': 'off', // 暂时关闭
'vue/comment-directive': 'off',
'vue/multi-word-component-names': 'off',
'space-before-function-paren': 'off'
},
globals: {
wx: true
}
}
......@@ -40,4 +40,4 @@ function generateUploadTarget(src, dist) {
})
}
generateUploadTarget('./dist', '/website/prod/center-register')
generateUploadTarget('./dist', '/website/prod/center-register-show-h5')
......@@ -4,7 +4,8 @@
<meta charset="UTF-8" />
<link rel="icon" href="https://zws-imgs-pub.ezijing.com/pc/base/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理系统</title>
<title></title>
<script src="https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
<div id="app"></div>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -10,12 +10,14 @@
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
},
"dependencies": {
"@tinymce/tinymce-vue": "^3.2.8",
"axios": "^0.23.0",
"axios": "^0.21.3",
"blueimp-md5": "^2.19.0",
"clipboard": "^2.0.8",
"element-ui": "^2.15.6",
"qrcode.vue": "^1.7.0",
"qs": "^6.10.3",
"query-string": "^7.0.1",
"vant": "^2.12.44",
"vue": "^2.6.14",
"vue-router": "^3.5.2",
"vuedraggable": "^2.24.3",
......@@ -28,13 +30,13 @@
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-vue": "^7.20.0",
"sass": "1.43.3",
"vite": "^2.6.10",
"vite-plugin-vue2": "^1.9.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^7.17.0",
"sass": "^1.39.0",
"vite": "^2.5.3",
"vite-plugin-vue2": "^1.8.1",
"vue-template-compiler": "^2.6.14"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
HNvRVFt0FD3vltU7
\ No newline at end of file
......@@ -27,15 +27,6 @@ export function uploadFile(data) {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
/**
* 获取权限列表
*/
export function getPermissions(params) {
return httpRequest.get('/api/permissions/api/v1/user/permissions', { params })
}
// 获取可访问的所有项目
export function getCommonMap() {
export function getAllSetting() {
return httpRequest.get('/api/register/v1/util/common-map')
}
html * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
outline: none;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
}
ul,
ol,
li {
list-style: none;
}
em,
i {
font-style: normal;
}
strong,
b {
font-weight: normal;
}
img {
border: none;
}
input,
img {
vertical-align: middle;
}
a {
color: inherit;
text-decoration: none;
}
input,
button,
select,
textarea {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-appearance: none;
border: 0;
border-radius: 0;
font: inherit;
}
textarea:focus {
outline: 0;
html{
max-width: 600px;
margin: 0 auto;
}
:root {
--main-color: rgba(184, 1, 64, 1);
body {
background: #f7f7f7;
}
;(function (win, doc) {
const resize = 'orientationchange' in window ? 'orientationchange' : 'resize'
/* 使用rem 动态计算跟font-size值 */
function resizeRoot() {
const wWidth =
win.screen.width > 0
? win.innerWidth >= win.screen.width || win.innerWidth === 0
? win.screen.width
: win.innerWidth
: win.innerWidth
const wFsize = ((wWidth > 750 ? 750 : wWidth) / 750) * (IsPC() ? 50 : 100)
doc.documentElement.style.fontSize = wFsize + 'px'
}
win.addEventListener(resize, resizeRoot, false)
doc.addEventListener('DOMContentLoaded', resizeRoot, false)
})(window, document)
function IsPC() {
const userAgentInfo = navigator.userAgent
const Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']
let flagPc = true
for (let v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flagPc = false
break
}
}
return flagPc
}
This source diff could not be displayed because it is too large. You can view the blob instead.
$--color-primary: rgba(184, 1, 64, 1);
/* 改变 icon 字体路径变量,必需 */
$--font-path: 'element-ui/lib/theme-chalk/fonts';
@import 'element-ui/packages/theme-chalk/src/index';
<template>
<el-cascader :options="options" :props="props" clearable v-bind="$attrs" v-on="$listeners"></el-cascader>
</template>
<script>
import chinaAreaData from 'china-area-data'
const AreaTreeData = listToTree(codeToList('86', chinaAreaData), chinaAreaData)
function listToTree(list, data) {
return list.map(item => {
const items = codeToList(item.code, data)
if (items.length) {
item.children = listToTree(items, data)
}
return item
})
}
function codeToList(code, data) {
const results = []
const item = data[code]
for (const code in item) {
results.push({ code, name: item[code] })
}
return results
}
export default {
props: {
props: {
type: Object,
default() {
return { label: 'name', value: 'name', expandTrigger: 'hover' }
}
}
},
data() {
return {
options: AreaTreeData
}
}
}
</script>
<template>
<div class="app-card">
<div class="app-card-hd">
<slot name="header">
<h2 class="app-card-hd__title" v-if="title">{{ title }}</h2>
<slot name="header-aside"></slot>
</slot>
</div>
<div class="app-card-bd">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'AppCard',
props: { title: String }
}
</script>
<style>
.app-card {
background: #ffffff;
box-shadow: 0 1px 6px 0 rgb(228 232 235 / 20%);
border-radius: 8px;
margin-bottom: 20px;
padding: 32px;
}
.app-card-hd {
display: flex;
}
.app-card-hd__title {
flex: 1;
font-size: 18px;
font-weight: 700;
margin-bottom: 16px;
}
</style>
<template>
<div class="table-list">
<div class="table-list-hd">
<!-- 筛选 -->
<div class="table-list-filter" v-if="filters.length">
<el-form :inline="true" :model="params" ref="filterForm">
<template v-for="item in filters">
<el-form-item :label="item.label" :prop="item.prop" :key="item.prop">
<template v-if="item.slots">
<slot :name="item.slots" v-bind="{ params }"></slot>
</template>
<template v-else>
<!-- input -->
<el-input v-model="params[item.prop]" v-bind="item" clearable v-if="item.type === 'input'" />
<!-- select -->
<el-select
v-model="params[item.prop]"
clearable
v-bind="item"
v-if="item.type === 'select'"
@change="search"
>
<template v-for="(option, index) in item.options">
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
:key="index"
></el-option>
</template>
</el-select>
</template>
</el-form-item>
</template>
<el-form-item class="filter-buttons">
<el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
<el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
<el-button @click="showMoreFilter" v-if="hasMoreFilter">更多筛选</el-button>
</el-form-item>
</el-form>
</div>
<div class="table-list-hd-aside"><slot name="header-aside" /></div>
</div>
<slot></slot>
<!-- 主体 -->
<div class="table-list-bd">
<slot name="body" v-bind="{ data: dataList }">
<el-table
:data="dataList"
v-loading="loading"
v-bind="$attrs"
v-on="$listeners"
style="height: 100%"
ref="table"
>
<template v-for="item in columns">
<el-table-column v-bind="item" :key="item.prop" v-if="visible(item)">
<template v-slot:default="scope" v-if="item.slots || item.computed">
<slot :name="item.slots" v-bind="scope" v-if="item.slots"></slot>
<div v-html="item.computed(scope)" v-if="item.computed"></div>
</template>
</el-table-column>
</template>
</el-table>
</slot>
</div>
<!-- 底部 -->
<div class="table-list-ft">
<div style="padding: 10px 0">
<slot name="footer"></slot>
</div>
<el-pagination
class="table-list-pagination"
layout="total, prev, pager, next, sizes, jumper"
:page-sizes="[10, 20, 30, 50, 100]"
:page-size="page.size"
:total="page.total"
:current-page.sync="page.currentPage"
@size-change="pageSizeChange"
@current-change="fetchList()"
v-if="hasPagination"
>
</el-pagination>
</div>
<!-- 更多筛选 -->
<el-drawer title="更多筛选" :visible.sync="moreFilterVisible" ref="drawer">
<div class="more-filter-drawer">
<div class="more-filter">
<el-form :model="params" ref="moreFilterForm">
<template v-for="item in moreFilters">
<el-form-item :label="item.label" :prop="item.prop" :key="item.prop">
<template v-if="item.slots">
<slot :name="item.slots" v-bind="{ params }"></slot>
</template>
<template v-else>
<!-- input -->
<el-input v-model="params[item.prop]" v-bind="item" clearable v-if="item.type === 'input'" />
<!-- select -->
<el-select
v-model="params[item.prop]"
clearable
v-bind="item"
v-if="item.type === 'select'"
style="width: 100%"
>
<template v-for="(option, index) in item.options">
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
:key="index"
></el-option>
</template>
</el-select>
</template>
</el-form-item>
</template>
</el-form>
</div>
<div class="more-filter-buttons">
<el-button @click="cancelMoreFilter">取 消</el-button>
<el-button type="primary" @click="primaryMoreFilter">确定</el-button>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
export default {
name: 'AppList',
props: {
// 接口请求
remote: { type: Object, default: () => ({}) },
// 筛选
filters: { type: Array, default: () => [] },
// 更多筛选
moreFilters: { type: Array, default: () => [] },
// 列表项
columns: { type: Array, default: () => [] },
// 列表数据
data: { type: Array, default: () => [] },
// 是否含有翻页
hasPagination: { type: Boolean, default: true },
// 每页多少条数据
limit: { type: Number, default: 20 }
},
data() {
return {
loading: false,
params: this.remote.params || {},
dataList: this.data,
page: { total: 0, size: this.limit, currentPage: 1 },
moreFilterVisible: false
}
},
watch: {
'remote.params': {
immediate: true,
handler(data) {
this.params = data || {}
}
},
data: {
immediate: true,
handler(data) {
this.dataList = data
}
}
},
computed: {
table() {
return this.$refs.table
},
hasMoreFilter() {
return !!this.moreFilters.length
}
},
methods: {
fetchList(isReset) {
/**
* @param function httpRequest api接口
* @param function beforeRequest 接口请求之前
* @param function callback 接口请求成功回调
*/
const { httpRequest, beforeRequest, callback } = this.remote
if (!httpRequest) {
return
}
// 参数设置
let params = this.params
// 翻页参数设置
if (this.hasPagination) {
params.page = (this.page.currentPage).toString()
params['per-page'] = this.page.size.toString()
}
// 接口请求之前
if (beforeRequest) {
params = beforeRequest(params, isReset)
}
// for (const key in params) {
// if (params[key] === '' || params[key] === undefined || params[key] === undefined) {
// delete params[key]
// }
// }
this.loading = true
httpRequest(params)
.then(res => {
const { data = [] } = res || {}
this.page.total = res.data.total
this.dataList = callback ? callback(data.list) : data.list
})
.catch(() => {
this.page.total = 0
this.dataList = []
})
.finally(() => {
this.loading = false
})
},
// 搜索
search() {
this.page.currentPage = 1
this.fetchList()
},
// 重置
reset() {
// 清空筛选条件
this.$refs.filterForm && this.$refs.filterForm.resetFields()
// 清空更多筛选条件
this.hasMoreFilter && this.$refs.moreFilterForm && this.$refs.moreFilterForm.resetFields()
// 初始化页码
this.page.currentPage = 1
// 刷新列表
this.fetchList(true)
},
// 刷新
refetch(isForce) {
isForce ? this.reset() : this.fetchList()
},
// 页数改变
pageSizeChange(value) {
this.page.currentPage = 1
this.page.size = value
this.fetchList()
},
visible(item) {
return Object.prototype.hasOwnProperty.call(item, 'visible') ? item.visible : true
},
// 显示更多筛选
showMoreFilter() {
this.moreFilterVisible = true
},
// 取消更多筛选
cancelMoreFilter() {
this.moreFilterVisible = false
// 清空筛选条件
this.$refs.moreFilterForm && this.$refs.moreFilterForm.resetFields()
},
// 确定更多筛选
primaryMoreFilter() {
this.moreFilterVisible = false
this.search()
}
},
beforeMount() {
this.fetchList()
}
}
</script>
<style lang="scss">
.table-list {
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.table-list-hd {
display: flex;
}
.table-list-filter {
flex: 1;
}
.table-list-bd {
flex: 1;
}
.table-list-ft {
display: flex;
align-items: center;
justify-content: space-between;
}
.table-list-pagination {
padding: 10px 0;
text-align: right;
}
.el-table-column--selection .cell {
padding: 0 14px !important;
}
.more-filter-drawer {
height: 100%;
display: flex;
flex-direction: column;
padding: 0 20px 20px;
box-sizing: border-box;
}
.more-filter {
flex: 1;
overflow-y: auto;
}
.more-filter-buttons {
display: flex;
.el-button {
flex: 1;
}
}
</style>
<template>
<div class="user-autocomplete">
<el-select v-model="searchType" style="width: 120px">
<el-option label="用户名" value="username"></el-option>
<el-option label="手机号" value="mobile"></el-option>
<el-option label="邮箱" value="email"></el-option>
<el-option label="昵称" value="nickname"></el-option>
</el-select>
<el-select
placeholder="搜索"
filterable
remote
style="width: 100%"
:remote-method="fetchUserList"
:loading="loading"
@change="handleChange"
clearable
v-bind="$attrs"
v-on="$listeners"
>
<el-option :label="user.realname || user.nickname" :value="user.id" v-for="user in userList" :key="user.id">
<div style="display: flex">
<span>
{{ user.realname || user.nickname }}
<template v-if="user.mobile">(手机号:{{ user.mobile }})</template>
</span>
<span class="t1" v-if="user.email">邮箱:{{ user.email }}</span>
<span class="t1" v-else>ID:{{ user.id }}</span>
</div>
</el-option>
</el-select>
</div>
</template>
<script>
import { userSearch } from '@/api/base'
export default {
data() {
return {
searchType: 'nickname',
userList: [],
loading: false
}
},
methods: {
fetchUserList(searchValue) {
const params = {}
params[this.searchType] = searchValue
this.loading = true
userSearch(params)
.then(response => {
this.userList = response.data.items
})
.finally(() => {
this.loading = false
})
},
handleChange(userId) {
const user = this.userList.find(user => user.id === userId)
this.$emit('change', userId, user)
}
}
}
</script>
<style lang="scss">
.user-autocomplete {
display: flex;
.el-select + .el-select {
margin-left: 10px;
}
.t1 {
color: #8492a6;
font-size: 13px;
margin: 0 20px 0 10px;
}
}
</style>
<template>
<el-dialog v-bind="$attrs" v-on="$listeners" append-to-body title="选择成员" width="60%">
<app-list v-bind="tableOptions" ref="list" @select="select" @selection-change="handleSelectionChange"></app-list>
<div class="dialog-footer">
<el-button @click="handleCancel">取 消</el-button>
<el-button type="primary" @click="handlePrimary">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { getUserList } from '@/api/base.js'
export default {
props: { multiple: { type: Boolean, default: true } },
data() {
return {
dialogVisible: false,
multipleSelection: [], // 选择的数据
selected: [] // 确定选中的
}
},
computed: {
// 列表配置
tableOptions() {
return {
remote: {
httpRequest: getUserList,
params: { app_id: this.$store.state.appid }
},
columns: [
{ type: 'selection' },
{ label: '姓名', prop: 'sso_user.realname' },
{ label: '昵称', prop: 'sso_user.nickname' },
{ label: '手机号', prop: 'sso_user.mobile' },
{ label: '邮箱', prop: 'sso_user.email' }
]
}
}
},
methods: {
// 选择
select(selection, row) {
if (!this.multiple && selection.length > 1) {
const selected = !!selection.find(item => item.id === row.id)
this.$refs.list.table.clearSelection()
this.$nextTick(function () {
this.$refs.list.table.toggleRowSelection(row, selected)
})
}
},
// 选择
handleSelectionChange(value) {
this.multipleSelection = value
},
// 取消
handleCancel() {
this.$emit('update:visible', false)
},
// 确定
handlePrimary() {
this.$emit('primary', this.multipleSelection)
}
}
}
</script>
<style lang="scss" scoped>
.dialog-footer {
position: sticky;
bottom: 0;
text-align: center;
z-index: 118;
padding: 20px 0;
border-top: 0.5px solid rgba(0, 0, 0, 0.05);
background-color: rgba(255, 255, 255, 0.95);
}
</style>
<template>
<aside class="app-aside">
<nav class="nav">
<el-menu :default-active="defaultActive" :router="true">
<template v-for="item in menuList">
<el-submenu :index="item.path" :key="item.path" v-if="item.children">
<template #title><i :class="item.icon"></i>{{ item.name }}</template>
<el-menu-item :index="subitem.path" v-for="subitem in item.children" :key="subitem.path">
{{ subitem.name }}
</el-menu-item>
</el-submenu>
<el-menu-item :index="item.path" :key="item.path" v-else>
<i :class="item.icon"></i>{{ item.name }}
</el-menu-item>
</template>
</el-menu>
</nav>
</aside>
</template>
<script>
export default {
name: 'AppAside',
data() {
return {
menuList: [
{ name: 'Banner管理', path: '/banner/list', icon: 'el-icon-notebook-2' },
{ name: '功能区管理', path: '/menu/list', icon: 'el-icon-user' },
{ name: '图文管理', path: '/essay/list', icon: 'el-icon-connection' },
{ name: '页面管理', path: '/pages/list', icon: 'el-icon-connection' }
]
}
},
computed: {
defaultActive() {
// 扁平菜单
const flatMenuList = this.menuList.reduce((result, item) => {
result.push(item)
if (item.children) {
result = result.concat(item.children)
}
return result
}, [])
const found = flatMenuList.reverse().find(item => {
return this.$route.path.includes(item.path)
})
return found ? found.path : '/'
},
// 菜单权限
menuPermissions() {
return this.$store.state.permissions.filter(item => item.type === 2)
}
},
methods: {
menuVisible(tag) {
if (!tag) {
return true
}
return !!this.menuPermissions.find(item => item.tag === tag)
}
}
}
</script>
<style lang="scss">
.app-aside {
position: sticky;
top: 0;
width: 200px;
z-index: 100;
background: #fff;
border-right: 1px solid rgba(0, 0, 0, 0.12);
overflow-x: hidden;
overflow-y: auto;
flex: 0 0 200px;
}
.nav {
margin: 20px 0;
.el-menu {
border-right: 0;
i {
margin-right: 14px;
font-size: 24px;
}
.el-icon-arrow-down {
margin-right: 0;
font-size: 16px;
}
}
.el-menu-item {
display: flex;
align-items: center;
margin: 0 16px;
font-size: 16px;
border-radius: 8px;
}
.el-submenu .el-menu-item {
min-width: auto;
padding-left: 58px !important;
}
.el-submenu__title {
display: flex;
align-items: center;
margin: 0 16px;
font-size: 16px;
border-radius: 8px;
&:hover {
background-color: rgba(86, 100, 210, 0.04);
}
}
}
</style>
<template>
<div class="app-breadcrumb" v-if="routes.length">
<el-breadcrumb>
<el-breadcrumb-item v-for="route in routes" :key="route.path">
<router-link :to="route.path">{{ route.meta.title }}</router-link>
</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
<script>
export default {
name: 'AppBreadcrumb',
computed: {
routes() {
return this.$route.matched.filter(route => route.meta.title)
}
}
}
</script>
<style lang="scss">
.app-breadcrumb {
padding: 18px 0 32px;
.el-breadcrumb {
font-size: 20px;
font-weight: 400;
line-height: 1;
}
.el-breadcrumb__inner a {
font-weight: normal;
color: #5b91fd;
}
.router-link-active {
color: #1a1b1c;
}
}
</style>
<template>
<header class="app-header">
<div class="logo">
<router-link to="/"><img src="https://webapp-pub.ezijing.com/highway/admin/logo.png" /></router-link>
</div>
<div class="app-header-right">
<el-dropdown>
<div class="avatar">
<img :src="user.avatar || 'https://zws-imgs-pub.ezijing.com/pc/base/logo.png'" />
</div>
<el-dropdown-menu slot="dropdown">
<div class="user">
<div class="user-name">{{ user.realname || user.nickname }}</div>
<el-button round size="medium" class="btn-logout" @click="logout">退出登录</el-button>
</div>
</el-dropdown-menu>
</el-dropdown>
</div>
</header>
</template>
<script>
export default {
name: 'AppHeader',
computed: {
user() {
return this.$store.state.user
}
},
methods: {
logout() {
this.$store.dispatch('logout').then(() => {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(window.location.href)}`
})
}
}
}
</script>
<style lang="scss">
.app-header {
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
height: 64px;
background-color: #fff;
border-bottom: 4px solid var(--main-color);
color: #5F5F5F;
.logo {
// width: 120px;
}
}
.app-header-right {
display: flex;
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
overflow: hidden;
}
}
}
.user {
padding: 16px;
}
.user-name {
margin-bottom: 20px;
}
.btn-logout {
width: 200px;
}
</style>
<template>
<div class="app-layout">
<app-header></app-header>
<div class="app-layout-container">
<app-aside></app-aside>
<app-main></app-main>
</div>
</div>
</template>
<script>
import AppHeader from './Header.vue'
import AppAside from './Aside.vue'
import AppMain from './Main.vue'
export default {
name: 'AppLayout',
components: { AppHeader, AppAside, AppMain }
}
</script>
<style>
.app-layout {
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #ededed;
}
.app-layout-container {
flex: 1;
display: flex;
}
</style>
<template>
<section class="app-main">
<div class="app-main-inner">
<div class="app-main-header">
<app-breadcrumb v-if="hasBreadcrumb"></app-breadcrumb>
</div>
<div class="app-main-container">
<router-view></router-view>
</div>
</div>
</section>
</template>
<script>
import AppBreadcrumb from './Breadcrumb.vue'
export default {
name: 'AppMain',
props: { hasBreadcrumb: { type: Boolean, default: true } },
components: { AppBreadcrumb }
}
</script>
<style>
.app-main {
position: relative;
flex: 1;
padding: 20px;
overflow: hidden;
}
.app-main-inner {
margin: 0 auto;
}
.app-main-container::after {
content: '';
display: table;
clear: both;
}
.el-form--label-top .el-form-item__label {
padding-bottom: 0;
}
</style>
<template>
<editor :init="init" v-bind="$attrs" v-on="$listeners" @onChange="onChange" @onBlur="onBlur" />
</template>
<script>
import Editor from '@tinymce/tinymce-vue'
import ImageUpload from './imageUpload'
export default {
props: {
maxHeight: {
type: Number
}
},
components: {
editor: Editor
},
data() {
return {
init: {
min_height: this.maxHeight || 400,
max_height: 600,
menubar: false,
statusbar: false,
plugins: 'table autoresize charmap fullscreen hr lists link code preview quickbars',
toolbar:
'undo redo | fontsizeselect lineheight bold italic underline strikethrough forecolor backcolor | link quickimage image media table | align hangingindent indent outdent numlist bullist | charmap blockquote hr fullscreen | code preview',
// font_formats:
// '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Times New Roman',
fontsize_formats: '8px 10px 12px 14px 15px 16px 17px 18px 20px 24px',
lineheight_formats: '0.5 1 1.2 1.5 2',
images_upload_handler: ImageUpload,
automatic_uploads: true,
quickbars_insert_toolbar: false,
// style_formats: [{ title: '悬挂缩进', block: 'p', styles: { textIndent: '-2em', paddingLeft: '2em' } }],
content_style: 'img {max-width:100%;}'
}
}
},
methods: {
onChange(event, editor) {
this.dispatch('ElFormItem', 'el.form.change', editor.getContent())
},
onBlur(event, editor) {
this.dispatch('ElFormItem', 'el.form.blur', editor.getContent())
},
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root
let name = parent.$options.componentName
while (parent && (!name || name !== componentName)) {
parent = parent.$parent
if (parent) {
name = parent.$options.componentName
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params))
}
}
}
}
</script>
<style>
.tox .tox-tbtn--bespoke .tox-tbtn__select-label {
width: 4em !important;
}
</style>
import { getSignature, uploadFile } from '@/api/base'
import md5 from 'blueimp-md5'
export default function (blobInfo, succFun, failFun) {
const file = blobInfo.blob()
getSignature()
.then(response => {
const prefix = 'upload/admin/'
const fileName = file.name
const key = prefix + md5(fileName + new Date().getTime()) + fileName.substr(fileName.lastIndexOf('.'))
const { accessid, policy, signature, host } = response
const data = { key, OSSAccessKeyId: accessid, policy, signature, success_action_status: '200', file }
const fileUrl = `${host}/${key}`
uploadFile(data)
.then(() => {
succFun(fileUrl)
})
.catch(() => {
failFun('上传失败')
})
})
.catch(response => {
failFun('获取Signature失败')
})
}
<template>
<div class="app-upload">
<draggable
<!-- <draggable
v-model="fileList"
group="people"
class="file-list el-upload-list--picture-card"
@end="onEnd"
v-if="showFileList"
>
<div class="file-item" v-for="(file, index) in fileList" :key="index">
<!-- <el-image style="width: 100%; height: 100%" :src="file.url" :preview-src-list="fileList.map(item => item.url)"> -->
<img :src="file.url" />
<img :src="file" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePreview(file)">
<i class="el-icon-zoom-in"></i>
......@@ -19,14 +17,16 @@
</span>
</span>
</div>
</draggable>
</draggable> -->
<!-- <van-uploader v-model="fileList" multiple /> -->
<el-upload
action="https://webapp-pub.oss-cn-beijing.aliyuncs.com"
type="drag"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:show-file-list="false"
:on-exceed="handleExceed"
:on-remove="handleRemove"
list-type="picture-card"
:data="data"
v-bind="$attrs"
v-on="$listeners"
......@@ -44,10 +44,10 @@
<script>
import { getSignature } from '@/api/base'
import md5 from 'blueimp-md5'
import draggable from 'vuedraggable'
// import draggable from 'vuedraggable'
export default {
name: 'AppUpload',
components: { draggable },
// components: { draggable },
props: {
value: { type: [String, Array] },
prefix: { type: String, default: 'upload/shop-admin/' },
......@@ -120,10 +120,10 @@ export default {
this.fileList.push({ name: file.name, url: file.raw.url })
value = this.fileList
} else {
this.fileList = [file.raw.url]
this.fileList.push(file.raw.url)
value = file.raw.url
}
this.$emit('input', value)
this.$emit('input', this.fileList)
this.dispatch('ElFormItem', 'el.form.change', value)
},
// 删除
......@@ -144,8 +144,8 @@ export default {
this.$emit('input', this.fileList)
},
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root
var name = parent.$options.componentName
let parent = this.$parent || this.$root
let name = parent.$options.componentName
while (parent && (!name || name !== componentName)) {
parent = parent.$parent
......@@ -191,4 +191,13 @@ export default {
object-fit: cover;
}
}
.el-upload{
width: 100% !important;
border:none !important;
height: 155px !important;
border-radius: .2rem !important;
}
.el-upload-list__item{
width: 100% !important;
}
</style>
<template>
<app-upload class="avatar-uploader" accept="image/*" :show-file-list="false" v-bind="$attrs" v-on="$listeners">
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</app-upload>
<div>
<app-upload @input="input" class="avatar-uploader" accept="image/*" :show-file-list="false" ></app-upload>
</div>
</template>
<script>
import AppUpload from './Upload.vue'
......@@ -16,6 +15,11 @@ export default {
imageUrl() {
return this.$attrs.value
}
},
methods: {
input(imgs) {
this.$emit('input', imgs)
}
}
}
</script>
......
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import store from '@/store'
import modules from './modules'
import beforeEnter from '@/utils/beforeEnter'
import useWXShare from '@/utils/wx'
// 公共css
import './assets/css/base.css'
import '@/assets/css/base.css'
import './assets/rem/rem.js'
// Element-UI
import ElementUI from 'element-ui'
import './assets/theme/style.scss'
// 公共组件
import AppCard from './components/base/AppCard.vue'
import AppList from './components/base/AppList.vue'
import beforeEnter from './utils/beforeEnter'
// 注册element-ui组件
Vue.use(ElementUI, { size: 'small' })
import '@/assets/theme/index.css'
// 注册公共组件
Vue.component('AppCard', AppCard)
Vue.component('AppList', AppList)
// vant
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(ElementUI)
Vue.use(Vant)
// 注册模块
modules({ router, store })
router.beforeEach(beforeEnter)
// const originalPush = Router.prototype.push
// Router.prototype.push = function push(location) {
// return originalPush.call(this, location).catch(err => err)
// }
useWXShare()
new Vue({
store,
router,
......
import httpRequest from '@/utils/axios'
/**
* 新建banner
*/
export function createBanner(data) {
return httpRequest.post('/api/road/v1/backend/banner/create', data)
}
/**
* 获取应用列表
*/
export function getAppList(params) {
return httpRequest.get('/api/road/v1/backend/banner/list', { params })
}
/**
* 更新banner
*/
export function updateBanner(data) {
return httpRequest.post('/api/road/v1/backend/banner/update', data)
}
/**
* 获取banner详情
*/
export function getDetails(params) {
return httpRequest.get('/api/road/v1/backend/banner/view', { params })
}
/**
* 删除banner
*/
export function deleteBanner(data) {
return httpRequest.post('/api/road/v1/backend/banner/delete', data)
}
// /**
// * 获取应用列表
// */
// export function getAppList(params) {
// return httpRequest.get('/api/register/v1/activity/index', { params })
// }
// /**
// * 新建报名
// */
// export function createRegister(data) {
// return httpRequest.post('/api/register/v1/activity/create', data)
// }
// /**
// * 报名详情
// */
// export function getRegisterDetail(params) {
// return httpRequest.get('/api/register/v1/activity/view', { params })
// }
// /**
// * 更新报名
// */
// export function updateRegister(data) {
// return httpRequest.post('/api/register/v1/activity/update', data)
// }
// /**
// * 删除报名
// */
// export function deleteRegister(data) {
// return httpRequest.post('/api/register/v1/activity/delete', data)
// }
// /**
// * 停止活动
// */
// export function stopRegister(data) {
// return httpRequest.post('/api/register/v1/activity/drop', data)
// }
<template>
<div>
<el-form :disabled="!!$route.query.type" ref="form" :rules="rules" :model="data" label-width="100px">
<el-form-item label="按钮文案:" prop="title">
<el-input v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面展示:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: { type: Object, default: () => {} }
},
data() {
return {
form: {
edit: '',
btnText: ''
},
rules: {
title: [{ required: true, message: '请填写按钮文案', trigger: 'change' }],
desc: [{ required: true, message: '请填写页面内容', trigger: 'change' }]
}
}
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
}
},
mounted() {
console.log(this.data, 'display')
}
}
</script>
<style lang="scss">
.tox-notifications-container {
display: none !important;
}
</style>
<template>
<div class="form-box">
<el-form ref="form" :disabled="!!$route.query.type" :rules="rules" :model="data" size="mini" label-width="150px">
<div class="form-set-info">
<div class="sub-title">信息设置</div>
<el-checkbox-group v-model="checkList" @change="checkboxChange">
<div class="field-list" v-for="(item, index) in fieldList" :key="index">
<div class="field-list_title">{{ item.title }}</div>
<div class="field-list_content">
<el-checkbox
style="margin: 0 90px 10px 10px"
:disabled="cItem.disabled ? cItem.disabled : false"
:label="cItem.key"
v-for="cItem in item.fields"
:key="cItem.key"
>
<div class="checkbox">
{{ cItem.label }}&nbsp;&nbsp;&nbsp;必填:
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="1"
></el-radio
>
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="2"
></el-radio
>
</div>
</el-checkbox>
</div>
</div>
</el-checkbox-group>
</div>
<div class="form-set-pay">
<div class="sub-title">缴费设置</div>
<!--导入功能 新增 -->
<el-form-item label="批量导入功能:">
<el-radio v-model="data.can_import" :label="1">开启</el-radio>
<el-radio v-model="data.can_import" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="缴费功能:">
<el-radio v-model="data.can_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_pay" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_pay">
<el-form-item label="价格:" prop="pay_price">
<el-input style="width: 20%" v-model="data.pay_price"></el-input>
</el-form-item>
<el-form-item label="开票功能:">
<el-radio v-model="data.can_invoice" :label="1">开启</el-radio>
<el-radio v-model="data.can_invoice" :label="0">关闭</el-radio>
</el-form-item>
<!-- 缴费方式 新增-->
<el-form-item label="缴费方式:" prop="pay_type">
<el-select v-model="data.pay_type" multiple>
<el-option v-for="item in payType" :key="item.key" :label="item.value" :value="item.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="线下支付联系方式:" prop="offline_info" v-if="data.pay_type.includes('3')">
<el-input style="width: 20%" v-model="data.offline_info"></el-input>
</el-form-item>
<el-form-item label="线下支付信息:" prop="offline_more_info" v-if="data.pay_type.includes('3')">
<v-editor style="width: 500px" :maxHeight="200" :disabled="!!$route.query.type" v-model="data.offline_more_info"></v-editor>
</el-form-item>
<el-form-item label="单位优惠:">
<el-radio v-model="data.can_company" :label="1">开启</el-radio>
<el-radio v-model="data.can_company" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="单位优惠金额:" prop="company_price" v-if="data.can_company">
<el-input style="width: 20%" v-model="data.company_price"></el-input>
</el-form-item>
<el-form-item label="跳转:">
<el-radio v-model="data.can_jump" :label="1">开启</el-radio>
<el-radio v-model="data.can_jump" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_jump">
<el-form-item label="跳转链接:" prop="jump_url">
<el-input style="width: 20%" v-model="data.jump_url"></el-input>
</el-form-item>
</template>
<el-form-item label="跳过支付:">
<el-radio v-model="data.can_skip_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_skip_pay" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="跳过文案:" prop="skip_pay_title" v-if="!!data.can_skip_pay">
<el-input style="width: 20%" v-model="data.skip_pay_title"></el-input>
</el-form-item>
<el-form-item label="支付平台:" prop="shop_id">
<el-select v-model="data.shop_id" placeholder="请选择">
<el-option v-for="item in shopMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
</template>
</div>
<div class="form-set-page">
<div class="sub-title">页面设置</div>
<el-form-item label="标题:" prop="title">
<el-input style="width: 20%" v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面头部:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: {
type: Object,
default: () => {}
}
},
data() {
return {
payType: [
{ key: '1', value: '微信' },
{ key: '2', value: '支付宝' },
{ key: '3', value: '线下支付' }
],
rules: {
title: { required: true, message: '请填写标题', trigger: 'blur' },
pay_price: [
{ required: true, message: '请填写支付金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('支付金额不能小于等于0元'))
}
}
}
],
jump_url: { required: true, message: '请填写跳转链接', trigger: 'blur' },
shop_id: { required: true, message: '请选择支付平台', trigger: 'change' },
skip_pay_title: { required: true, message: '请填写跳过支付文案', trigger: 'blur' },
pay_type: { required: true, message: '请填选择缴费方式', trigger: 'change' },
company_price: [
{ required: true, message: '请填写单位优惠金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('优惠金额不能小于等于0元'))
}
}
}
]
},
options: [],
checkList: [],
fieldList: [
{
title: '个人信息',
fields: [
{ key: 'name', label: '姓名', required: '1', disabled: true },
{ key: 'mobile', label: '电话', required: '1', disabled: true },
{ key: 'gender', label: '性别', required: '1' },
{ key: 'email', label: '邮箱', required: '1' },
{ key: 'company', label: '公司', required: '1' },
{ key: 'position', label: '职位', required: '1' },
{ key: 'number', label: '编号', required: '1' },
{ key: 'country', label: '国籍', required: '1' },
{ key: 'provinces', label: '省份', required: '1' },
{ key: 'city', label: '城市', required: '1' },
{ key: 'address', label: '地址', required: '1' },
{ key: 'fixed_telephone', label: '固话', required: '1' },
{ key: 'industry', label: '行业', required: '1' },
{ key: 'id_number', label: '身份证号码', required: '1' }
]
},
{
title: '社交信息',
fields: [
{ key: 'wechat', label: '微信', required: '1' },
{ key: 'qq', label: 'QQ', required: '1' },
{ key: 'ding', label: '钉钉', required: '1' },
{ key: 'weibo', label: '微博', required: '1' }
]
},
{
title: '入住信息',
fields: [
{ key: 'check_in_time', label: '入住时间', required: '1' },
{ key: 'check_out_time', label: '离店时间', required: '1' },
{ key: 'room_type', label: '房型', required: '1' },
{ key: 'breakfast', label: '早餐', required: '1' }
]
}
]
}
},
computed: {
shopMap() {
return this.$store.state.commonMap.details_shop_map
},
payTypeMap() {
return this.data.pay_type
}
},
created() {},
mounted() {
this.setInfoFields()
},
methods: {
// 信息设置数据回显
setInfoFields() {
this.fieldList = this.fieldList.reduce((a, b) => {
b.fields.map(item => {
const findData = this.data.user_fields.find(fData => fData.key === item.key)
if (findData) {
this.checkList.push(findData.key)
item.required = findData.required ? '1' : '2'
}
return item
})
a.push(b)
return a
}, [])
},
// 信息设置选择后 吧选择的编程后台需要的数据
checkboxChange() {
this.data.user_fields = this.fieldList.reduce((a, b) => {
b.fields.forEach(item => {
const findData = this.checkList.find(fData => fData === item.key)
if (findData) {
a.push({ key: item.key, required: !!(item.required === '1'), enable_edit: true })
}
})
return a
}, [])
this.data.pay_type = this.data.pay_type.toString()
},
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
this.checkboxChange()
flag = true
}
})
return flag
}
}
}
</script>
<style lang="scss" scoped>
.sub-title {
line-height: 100%;
font-size: 16px;
font-weight: bold;
color: #333333;
border-left: 3px solid rgba(184, 1, 64, 1);
padding-left: 7px;
margin-bottom: 25px;
}
.form-box {
padding-top: 15px;
}
::v-deep {
.form-set-info {
.el-form-item__content {
display: flex;
align-items: center;
}
.el-icon-remove-outline {
font-size: 22px;
margin-left: 10px;
color: rgba(214, 214, 214, 1);
cursor: pointer;
}
.required {
margin-left: 15px;
}
}
}
.form-set-pay {
border-bottom: 1px solid #d6d6d6;
padding: 25px 0 15px;
}
.form-set-page {
padding: 25px 0 15px;
border-bottom: 1px solid #d6d6d6;
}
.form-set-info {
border-bottom: 1px solid #d6d6d6;
padding-bottom: 30px;
.field-list {
margin-bottom: 30px;
.field-list_title {
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
}
.field-list_content {
padding-top: 15px;
.checkbox {
display: flex;
align-items: center;
}
}
}
}
</style>
<template>
<div>
<el-form ref="form" :disabled="!!$route.query.type" :inline="true" :rules="rules" :model="form">
<el-form-item label="页面标题:" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="活动名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="人数限制:" prop="max_number">
<el-input v-model="form.max_number"></el-input>
</el-form-item>
<el-form-item label="关联项目:" prop="project_id">
<el-select v-model="form.project_id" placeholder="请选择">
<el-option v-for="item in projectMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="活动开始时间:" prop="activity_time">
<el-date-picker
v-model="form.activity_time"
type="datetime"
@change="activityDateChange"
placeholder="选择日期时间"
:picker-options="pickerOptions"
>
</el-date-picker>
</el-form-item>
<el-form-item label="报名时间:" prop="time">
<el-date-picker
@change="dateChange"
v-model="form.time"
type="datetimerange"
range-separator="至"
start-placeholder="报名开始日期"
end-placeholder="报名结束日期"
>
</el-date-picker>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
form: { type: Object, default: () => {} }
},
data() {
return {
rules: {
title: { required: true, message: '请填写页面标题', trigger: 'blur' },
name: { required: true, message: '请填写活动标题', trigger: 'blur' },
max_number: [
{ required: true, message: '请填写最大参与人数', trigger: 'blur' },
{
trigger: 'blur',
min: 1,
message: '最大人数限制不能小于1人',
validator(rule, value, callback) {
if (parseInt(Number(value)) && Number(value) >= 1) {
callback()
} else {
callback(new Error('最大人数限制不能小于1人'))
}
}
}
],
project_id: { required: true, message: '请关联项目', trigger: 'change' },
time: { required: true, message: '请选择时间', trigger: 'change' },
activity_time: { required: true, message: '请选择时间', trigger: 'change' }
},
pickerOptions: {
disabledDate(v) {
return v.getTime() < new Date().getTime() - 86400000
}
}
}
},
computed: {
projectMap() {
return this.$store.state.commonMap.project_map || {}
}
},
mounted() {
console.log(this.form)
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
},
// 日期改变的时候。吧日期转成后台需要的格式
dateChange(date) {
this.form.start_time = this.setDate(date[0])
this.form.end_time = this.setDate(date[1])
},
setDate(val) {
const d = new Date(val)
const date = `${d.getFullYear()}-${this.toDo(d.getMonth() + 1)}-${this.toDo(d.getDate())} ${this.toDo(
d.getHours()
)}:${this.toDo(d.getMinutes())}:${this.toDo(d.getSeconds())}`
return date
},
toDo(n) {
return n < 10 ? `0${n}` : n
},
activityDateChange() {
this.form.activity_time = this.setDate(this.form.activity_time)
}
}
}
</script>
<style lang="scss" scoped></style>
import AppLayout from '@/components/layout/Index.vue'
const routes = [
{
path: '/banner',
component: AppLayout,
children: [
{ path: 'list', component: () => import('./views/List.vue') },
{ path: 'Update', component: () => import('./views/Update.vue') }
]
}
]
export { routes }
<template>
<app-card class="register-box">
<app-list v-bind="tableOptions" ref="list">
<div class="line"></div>
<div class="btn-box">
<el-button type="primary" @click="$router.push({ path: '/banner/update' })">新建Banner</el-button>
</div>
<template v-slot:filter-time>
<el-date-picker
v-model="filterDate"
@change="changeDate"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</template>
<template v-slot:picture="{ row }">
<div :style="`background-image:url(${row.picture});background-size: cover;width:200px;height:100px;`"></div>
</template>
<template v-slot:release-status="{ row }">
<el-switch v-model="row.status" @change="updateStatus(row)"> </el-switch>
</template>
<template v-slot:sort-select="{ row }">
<el-select v-model="row.sort" placeholder="请选择" @change="updateStatus(row)">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</template>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleEdit(row)">编辑</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
</app-list>
</app-card>
</template>
<script>
// 接口
import { getAppList, updateBanner, deleteBanner } from '../api'
export default {
data() {
const count = []
for (let i = 0; i < 100; i++) {
count.push({ value: i, options: i })
}
return {
value1: '',
filterDate: '',
options: count,
createdStart: '',
createdEnd: ''
}
},
computed: {
// 列表配置
tableOptions() {
return {
limit: 10,
remote: {
httpRequest: getAppList,
params: {
title: '',
status: '',
created_time_start: this.createdStart,
created_time_end: this.createdEnd
},
callback: res => {
res.map(item => {
item.status = !!parseInt(item.status)
return item
})
return res
}
},
filters: [
{
type: 'input',
prop: 'title',
label: '标题:'
},
{
type: 'select',
prop: 'status',
label: '发布状态:',
options: [
{ value: '0', label: '未发布' },
{ value: '1', label: '已发布' }
]
},
{
slots: 'filter-time',
label: '创建时间:'
}
],
columns: [
{ label: 'id', prop: 'id', align: 'center' },
{ label: '标题', prop: 'title', align: 'center' },
{ label: '图片', slots: 'picture', align: 'center', width: '200px' },
{
label: '发布状态',
slots: 'release-status',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '排序', slots: 'sort-select', align: 'center' },
{ label: '操作', slots: 'table-x', align: 'center' }
]
}
}
},
methods: {
// 时间搜索
changeDate() {
if (this.filterDate) {
this.createdStart = this.filterDate[0]
this.createdEnd = this.filterDate[1]
} else {
this.createdStart = ''
this.createdEnd = ''
// this.$refs.list.refetch(true)
}
},
// 更新状态
updateStatus(row) {
const params = row
params.status = row.status ? '1' : '0'
updateBanner(row).then(res => {
if (res.code === 0) {
this.$message({
message: '修改成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
},
handleEdit(row) {
this.$router.push({ path: '/banner/update', query: { id: row.id } })
},
handleDelete(row) {
deleteBanner({ id: row.id }).then(res => {
if (res.code === 0) {
this.$message({
message: '删除成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
}
}
}
</script>
<style lang="scss">
.register-box {
.el-form-item {
margin-right: 20px !important;
}
.line {
// border-top: 1px solid #D6D6D6;
height: 1px;
background: #d6d6d6;
margin: 8px 0 23px;
box-sizing: border-box;
}
.btn-box {
margin-bottom: 16px;
}
}
</style>
<template>
<div class="create-box">
<app-card :title="!$route.query.id ? '新建Banner' : '编辑Banner'">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
style="width: 40%; margin: 0 auto"
>
<el-form-item label="标题">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item label="上传banner" prop="banner">
<upload-image v-model="ruleForm.picture"></upload-image>
</el-form-item>
<el-form-item label="是否发布" prop="status">
<el-switch v-model="status"></el-switch>
</el-form-item>
<el-form-item label="关联选择">
<el-button type="primary" @click="drawer = true">点击选择</el-button>
</el-form-item>
<el-form-item>
<div style="padding-top: 20px">
<el-button type="primary" @click="submitForm">确认</el-button>
<el-button @click="drawer = true">取消</el-button>
</div>
</el-form-item>
</el-form>
</app-card>
<el-drawer size="40%" :visible.sync="drawer" :direction="direction">
<div style="padding: 0 20px">
<el-tabs v-model="activeName">
<el-tab-pane label="关联图文" name="1"></el-tab-pane>
<el-tab-pane label="关联页面" name="2"></el-tab-pane>
<el-tab-pane label="跳转链接" name="3"></el-tab-pane>
</el-tabs>
</div>
</el-drawer>
</div>
</template>
<script>
import UploadImage from '@/components/upload/UploadImage.vue'
import { createBanner, getDetails, updateBanner } from '../api'
export default {
components: {
UploadImage
},
data() {
return {
activeName: '1',
status: true,
drawer: false,
direction: 'rtl',
ruleForm: {
title: '',
url: '',
picture: '',
type: '',
status: true,
relations_id: ''
},
rules: {
banner: [{ required: true, message: '请上传banner', trigger: 'blur' }],
status: [{ required: true, message: '', trigger: 'blur' }]
}
}
},
computed: {
id() {
return this.$route.query.id
}
},
methods: {
// 提交
submitForm() {
this.ruleForm.type = this.activeName
this.ruleForm.status = this.status ? 1 : 0
if (this.id) {
updateBanner(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '编辑成功',
type: 'success'
})
this.$router.go(-1)
}
})
} else {
createBanner(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '提交成功',
type: 'success'
})
this.$router.go(-1)
}
})
}
},
// 获取详情
getDetails() {
getDetails({ id: this.id }).then(res => {
this.status = !!parseInt(res.data.status)
this.ruleForm = res.data
})
}
},
mounted() {
if (this.id) {
this.getDetails()
}
}
}
</script>
<style lang="scss" scoped></style>
import httpRequest from '@/utils/axios'
/**
* 新建图文
*/
export function createEssay(data) {
return httpRequest.post('/api/road/v1/backend/doc/create', data)
}
/**
* 获取应用列表
*/
export function getAppList(params) {
return httpRequest.get('/api/road/v1/backend/doc/list', { params })
}
/**
* 更新图文
*/
export function updateEssay(data) {
return httpRequest.post('/api/road/v1/backend/doc/update', data)
}
/**
* 获取图文详情
*/
export function getDetails(params) {
return httpRequest.get('/api/road/v1/backend/doc/view', { params })
}
/**
* 删除图文
*/
export function deleteEssay(data) {
return httpRequest.post('/api/road/v1/backend/doc/delete', data)
}
// /**
// * 获取应用列表
// */
// export function getAppList(params) {
// return httpRequest.get('/api/register/v1/activity/index', { params })
// }
// /**
// * 新建报名
// */
// export function createRegister(data) {
// return httpRequest.post('/api/register/v1/activity/create', data)
// }
// /**
// * 报名详情
// */
// export function getRegisterDetail(params) {
// return httpRequest.get('/api/register/v1/activity/view', { params })
// }
// /**
// * 更新报名
// */
// export function updateRegister(data) {
// return httpRequest.post('/api/register/v1/activity/update', data)
// }
// /**
// * 删除报名
// */
// export function deleteRegister(data) {
// return httpRequest.post('/api/register/v1/activity/delete', data)
// }
// /**
// * 停止活动
// */
// export function stopRegister(data) {
// return httpRequest.post('/api/register/v1/activity/drop', data)
// }
<template>
<div>
<el-form :disabled="!!$route.query.type" ref="form" :rules="rules" :model="data" label-width="100px">
<el-form-item label="按钮文案:" prop="title">
<el-input v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面展示:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: { type: Object, default: () => {} }
},
data() {
return {
form: {
edit: '',
btnText: ''
},
rules: {
title: [{ required: true, message: '请填写按钮文案', trigger: 'change' }],
desc: [{ required: true, message: '请填写页面内容', trigger: 'change' }]
}
}
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
}
},
mounted() {
console.log(this.data, 'display')
}
}
</script>
<style lang="scss">
.tox-notifications-container {
display: none !important;
}
</style>
<template>
<div class="form-box">
<el-form ref="form" :disabled="!!$route.query.type" :rules="rules" :model="data" size="mini" label-width="150px">
<div class="form-set-info">
<div class="sub-title">信息设置</div>
<el-checkbox-group v-model="checkList" @change="checkboxChange">
<div class="field-list" v-for="(item, index) in fieldList" :key="index">
<div class="field-list_title">{{ item.title }}</div>
<div class="field-list_content">
<el-checkbox
style="margin: 0 90px 10px 10px"
:disabled="cItem.disabled ? cItem.disabled : false"
:label="cItem.key"
v-for="cItem in item.fields"
:key="cItem.key"
>
<div class="checkbox">
{{ cItem.label }}&nbsp;&nbsp;&nbsp;必填:
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="1"
></el-radio
>
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="2"
></el-radio
>
</div>
</el-checkbox>
</div>
</div>
</el-checkbox-group>
</div>
<div class="form-set-pay">
<div class="sub-title">缴费设置</div>
<!--导入功能 新增 -->
<el-form-item label="批量导入功能:">
<el-radio v-model="data.can_import" :label="1">开启</el-radio>
<el-radio v-model="data.can_import" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="缴费功能:">
<el-radio v-model="data.can_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_pay" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_pay">
<el-form-item label="价格:" prop="pay_price">
<el-input style="width: 20%" v-model="data.pay_price"></el-input>
</el-form-item>
<el-form-item label="开票功能:">
<el-radio v-model="data.can_invoice" :label="1">开启</el-radio>
<el-radio v-model="data.can_invoice" :label="0">关闭</el-radio>
</el-form-item>
<!-- 缴费方式 新增-->
<el-form-item label="缴费方式:" prop="pay_type">
<el-select v-model="data.pay_type" multiple>
<el-option v-for="item in payType" :key="item.key" :label="item.value" :value="item.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="线下支付联系方式:" prop="offline_info" v-if="data.pay_type.includes('3')">
<el-input style="width: 20%" v-model="data.offline_info"></el-input>
</el-form-item>
<el-form-item label="线下支付信息:" prop="offline_more_info" v-if="data.pay_type.includes('3')">
<v-editor style="width: 500px" :maxHeight="200" :disabled="!!$route.query.type" v-model="data.offline_more_info"></v-editor>
</el-form-item>
<el-form-item label="单位优惠:">
<el-radio v-model="data.can_company" :label="1">开启</el-radio>
<el-radio v-model="data.can_company" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="单位优惠金额:" prop="company_price" v-if="data.can_company">
<el-input style="width: 20%" v-model="data.company_price"></el-input>
</el-form-item>
<el-form-item label="跳转:">
<el-radio v-model="data.can_jump" :label="1">开启</el-radio>
<el-radio v-model="data.can_jump" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_jump">
<el-form-item label="跳转链接:" prop="jump_url">
<el-input style="width: 20%" v-model="data.jump_url"></el-input>
</el-form-item>
</template>
<el-form-item label="跳过支付:">
<el-radio v-model="data.can_skip_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_skip_pay" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="跳过文案:" prop="skip_pay_title" v-if="!!data.can_skip_pay">
<el-input style="width: 20%" v-model="data.skip_pay_title"></el-input>
</el-form-item>
<el-form-item label="支付平台:" prop="shop_id">
<el-select v-model="data.shop_id" placeholder="请选择">
<el-option v-for="item in shopMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
</template>
</div>
<div class="form-set-page">
<div class="sub-title">页面设置</div>
<el-form-item label="标题:" prop="title">
<el-input style="width: 20%" v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面头部:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: {
type: Object,
default: () => {}
}
},
data() {
return {
payType: [
{ key: '1', value: '微信' },
{ key: '2', value: '支付宝' },
{ key: '3', value: '线下支付' }
],
rules: {
title: { required: true, message: '请填写标题', trigger: 'blur' },
pay_price: [
{ required: true, message: '请填写支付金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('支付金额不能小于等于0元'))
}
}
}
],
jump_url: { required: true, message: '请填写跳转链接', trigger: 'blur' },
shop_id: { required: true, message: '请选择支付平台', trigger: 'change' },
skip_pay_title: { required: true, message: '请填写跳过支付文案', trigger: 'blur' },
pay_type: { required: true, message: '请填选择缴费方式', trigger: 'change' },
company_price: [
{ required: true, message: '请填写单位优惠金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('优惠金额不能小于等于0元'))
}
}
}
]
},
options: [],
checkList: [],
fieldList: [
{
title: '个人信息',
fields: [
{ key: 'name', label: '姓名', required: '1', disabled: true },
{ key: 'mobile', label: '电话', required: '1', disabled: true },
{ key: 'gender', label: '性别', required: '1' },
{ key: 'email', label: '邮箱', required: '1' },
{ key: 'company', label: '公司', required: '1' },
{ key: 'position', label: '职位', required: '1' },
{ key: 'number', label: '编号', required: '1' },
{ key: 'country', label: '国籍', required: '1' },
{ key: 'provinces', label: '省份', required: '1' },
{ key: 'city', label: '城市', required: '1' },
{ key: 'address', label: '地址', required: '1' },
{ key: 'fixed_telephone', label: '固话', required: '1' },
{ key: 'industry', label: '行业', required: '1' },
{ key: 'id_number', label: '身份证号码', required: '1' }
]
},
{
title: '社交信息',
fields: [
{ key: 'wechat', label: '微信', required: '1' },
{ key: 'qq', label: 'QQ', required: '1' },
{ key: 'ding', label: '钉钉', required: '1' },
{ key: 'weibo', label: '微博', required: '1' }
]
},
{
title: '入住信息',
fields: [
{ key: 'check_in_time', label: '入住时间', required: '1' },
{ key: 'check_out_time', label: '离店时间', required: '1' },
{ key: 'room_type', label: '房型', required: '1' },
{ key: 'breakfast', label: '早餐', required: '1' }
]
}
]
}
},
computed: {
shopMap() {
return this.$store.state.commonMap.details_shop_map
},
payTypeMap() {
return this.data.pay_type
}
},
created() {},
mounted() {
this.setInfoFields()
},
methods: {
// 信息设置数据回显
setInfoFields() {
this.fieldList = this.fieldList.reduce((a, b) => {
b.fields.map(item => {
const findData = this.data.user_fields.find(fData => fData.key === item.key)
if (findData) {
this.checkList.push(findData.key)
item.required = findData.required ? '1' : '2'
}
return item
})
a.push(b)
return a
}, [])
},
// 信息设置选择后 吧选择的编程后台需要的数据
checkboxChange() {
this.data.user_fields = this.fieldList.reduce((a, b) => {
b.fields.forEach(item => {
const findData = this.checkList.find(fData => fData === item.key)
if (findData) {
a.push({ key: item.key, required: !!(item.required === '1'), enable_edit: true })
}
})
return a
}, [])
this.data.pay_type = this.data.pay_type.toString()
},
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
this.checkboxChange()
flag = true
}
})
return flag
}
}
}
</script>
<style lang="scss" scoped>
.sub-title {
line-height: 100%;
font-size: 16px;
font-weight: bold;
color: #333333;
border-left: 3px solid rgba(184, 1, 64, 1);
padding-left: 7px;
margin-bottom: 25px;
}
.form-box {
padding-top: 15px;
}
::v-deep {
.form-set-info {
.el-form-item__content {
display: flex;
align-items: center;
}
.el-icon-remove-outline {
font-size: 22px;
margin-left: 10px;
color: rgba(214, 214, 214, 1);
cursor: pointer;
}
.required {
margin-left: 15px;
}
}
}
.form-set-pay {
border-bottom: 1px solid #d6d6d6;
padding: 25px 0 15px;
}
.form-set-page {
padding: 25px 0 15px;
border-bottom: 1px solid #d6d6d6;
}
.form-set-info {
border-bottom: 1px solid #d6d6d6;
padding-bottom: 30px;
.field-list {
margin-bottom: 30px;
.field-list_title {
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
}
.field-list_content {
padding-top: 15px;
.checkbox {
display: flex;
align-items: center;
}
}
}
}
</style>
<template>
<div>
<el-form ref="form" :disabled="!!$route.query.type" :inline="true" :rules="rules" :model="form">
<el-form-item label="页面标题:" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="活动名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="人数限制:" prop="max_number">
<el-input v-model="form.max_number"></el-input>
</el-form-item>
<el-form-item label="关联项目:" prop="project_id">
<el-select v-model="form.project_id" placeholder="请选择">
<el-option v-for="item in projectMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="活动开始时间:" prop="activity_time">
<el-date-picker
v-model="form.activity_time"
type="datetime"
@change="activityDateChange"
placeholder="选择日期时间"
:picker-options="pickerOptions"
>
</el-date-picker>
</el-form-item>
<el-form-item label="报名时间:" prop="time">
<el-date-picker
@change="dateChange"
v-model="form.time"
type="datetimerange"
range-separator="至"
start-placeholder="报名开始日期"
end-placeholder="报名结束日期"
>
</el-date-picker>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
form: { type: Object, default: () => {} }
},
data() {
return {
rules: {
title: { required: true, message: '请填写页面标题', trigger: 'blur' },
name: { required: true, message: '请填写活动标题', trigger: 'blur' },
max_number: [
{ required: true, message: '请填写最大参与人数', trigger: 'blur' },
{
trigger: 'blur',
min: 1,
message: '最大人数限制不能小于1人',
validator(rule, value, callback) {
if (parseInt(Number(value)) && Number(value) >= 1) {
callback()
} else {
callback(new Error('最大人数限制不能小于1人'))
}
}
}
],
project_id: { required: true, message: '请关联项目', trigger: 'change' },
time: { required: true, message: '请选择时间', trigger: 'change' },
activity_time: { required: true, message: '请选择时间', trigger: 'change' }
},
pickerOptions: {
disabledDate(v) {
return v.getTime() < new Date().getTime() - 86400000
}
}
}
},
computed: {
projectMap() {
return this.$store.state.commonMap.project_map || {}
}
},
mounted() {
console.log(this.form)
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
},
// 日期改变的时候。吧日期转成后台需要的格式
dateChange(date) {
this.form.start_time = this.setDate(date[0])
this.form.end_time = this.setDate(date[1])
},
setDate(val) {
const d = new Date(val)
const date = `${d.getFullYear()}-${this.toDo(d.getMonth() + 1)}-${this.toDo(d.getDate())} ${this.toDo(
d.getHours()
)}:${this.toDo(d.getMinutes())}:${this.toDo(d.getSeconds())}`
return date
},
toDo(n) {
return n < 10 ? `0${n}` : n
},
activityDateChange() {
this.form.activity_time = this.setDate(this.form.activity_time)
}
}
}
</script>
<style lang="scss" scoped></style>
import AppLayout from '@/components/layout/Index.vue'
const routes = [
{
path: '/essay',
component: AppLayout,
children: [
{ path: 'list', component: () => import('./views/List.vue') },
{ path: 'Update', component: () => import('./views/Update.vue') }
]
}
]
export { routes }
<template>
<app-card class="register-box">
<app-list v-bind="tableOptions" ref="list">
<div class="line"></div>
<div class="btn-box">
<el-button type="primary" @click="$router.push({ path: '/essay/update' })">新建图文</el-button>
</div>
<template v-slot:filter-time>
<el-date-picker
v-model="filterDate"
@change="changeDate"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</template>
<template v-slot:picture="{ row }">
<div :style="`background-image:url(${row.picture});background-size: cover;width:170px;height:80px;`"></div>
</template>
<template v-slot:release-status="{ row }">
<el-switch v-model="row.status" @change="updateStatus(row)"> </el-switch>
</template>
<template v-slot:sort-select="{ row }">
<el-select v-model="row.sort" placeholder="请选择" @change="updateStatus(row)">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</template>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleEdit(row)">编辑</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
</app-list>
</app-card>
</template>
<script>
// 接口
import { getAppList, updateEssay, deleteEssay } from '../api'
export default {
data() {
const count = []
for (let i = 0; i < 100; i++) {
count.push({ value: i, options: i })
}
return {
value1: '',
filterDate: '',
options: count,
createdStart: '',
createdEnd: ''
}
},
computed: {
// 列表配置
tableOptions() {
return {
limit: 10,
remote: {
httpRequest: getAppList,
params: {
title: '',
status: '',
created_time_start: this.createdStart,
created_time_end: this.createdEnd
},
callback: res => {
res.map(item => {
item.status = !!parseInt(item.status)
return item
})
return res
}
},
filters: [
{
type: 'input',
prop: 'title',
label: '标题:'
},
{
type: 'select',
prop: 'status',
label: '发布状态:',
options: [
{ value: '0', label: '未发布' },
{ value: '1', label: '已发布' }
]
},
{
slots: 'filter-time',
label: '创建时间:'
}
],
columns: [
{ label: 'id', prop: 'id', align: 'center' },
{ label: '封面图', slots: 'picture', align: 'center', width: '170px' },
{ label: '标题', prop: 'title', align: 'center' },
{ label: '摘要', prop: 'remark', align: 'center' },
{ label: '备注', prop: 'comment', align: 'center' },
{
label: '发布状态',
slots: 'release-status',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '排序', slots: 'sort-select', align: 'center' },
{ label: '操作', slots: 'table-x', align: 'center' }
]
}
}
},
methods: {
// 时间搜索
changeDate() {
if (this.filterDate) {
this.createdStart = this.filterDate[0]
this.createdEnd = this.filterDate[1]
} else {
this.createdStart = ''
this.createdEnd = ''
// this.$refs.list.refetch(true)
}
},
// 更新发布状态
updateStatus(row) {
const params = row
params.status = row.status ? '1' : '0'
updateEssay(row).then(res => {
if (res.code === 0) {
this.$message({
message: '修改成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
},
handleEdit(row) {
this.$router.push({ path: '/essay/update', query: { id: row.id } })
},
handleDelete(row) {
deleteEssay({ id: row.id }).then(res => {
if (res.code === 0) {
this.$message({
message: '删除成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
}
}
}
</script>
<style lang="scss">
.register-box {
.el-form-item {
margin-right: 20px !important;
}
.line {
// border-top: 1px solid #D6D6D6;
height: 1px;
background: #d6d6d6;
margin: 8px 0 23px;
box-sizing: border-box;
}
.btn-box {
margin-bottom: 16px;
}
}
</style>
<template>
<div class="create-box">
<app-card :title="!$route.query.id ? '新建菜单' : '编辑菜单'">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
style="width: 80%; margin: 0 auto"
>
<el-form-item label="封面图" prop="picture">
<upload-image v-model="ruleForm.picture"></upload-image>
</el-form-item>
<el-form-item label="标题" prop="title">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="ruleForm.comment"></el-input>
</el-form-item>
<el-form-item label="跳转链接">
<el-input v-model="ruleForm.url"></el-input>
</el-form-item>
<el-form-item label="摘要">
<el-input v-model="ruleForm.remark"></el-input>
</el-form-item>
<el-form-item label="正文" prop="content">
<v-editor v-model="ruleForm.content"></v-editor>
</el-form-item>
<el-form-item label="是否启用" prop="status">
<el-switch v-model="status"></el-switch>
</el-form-item>
<el-form-item label="关联选择">
<el-button type="primary" @click="drawer = true">点击选择</el-button>
</el-form-item>
<el-form-item>
<div style="padding-top: 20px; width: 200px; margin: 0 auto">
<el-button type="primary" @click="submitForm">确认</el-button>
<el-button @click="drawer = true">取消</el-button>
</div>
</el-form-item>
</el-form>
</app-card>
<el-drawer size="40%" :visible.sync="drawer" :direction="direction">
<div style="padding: 0 20px">
<el-tabs v-model="activeName">
<el-tab-pane label="关联图文" name="1"></el-tab-pane>
<el-tab-pane label="关联页面" name="2"></el-tab-pane>
<el-tab-pane label="跳转链接" name="3"></el-tab-pane>
</el-tabs>
</div>
</el-drawer>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
import UploadImage from '@/components/upload/UploadImage.vue'
import { createEssay, getDetails, updateEssay } from '../api'
export default {
components: {
UploadImage,
VEditor
},
data() {
return {
activeName: '1',
status: true,
drawer: false,
direction: 'rtl',
ruleForm: {
title: '',
comment: '',
url: '',
picture: '',
remark: '',
content: '',
status: true,
relations_id_page: '',
relations_id_banner: '',
relations_id_menu: ''
},
rules: {
title: [{ required: true, message: '请填写菜单名称', trigger: 'blur' }],
picture: [{ required: true, message: '请上传banner', trigger: 'blur' }],
status: [{ required: true, message: '', trigger: 'blur' }],
content: [{ required: true, message: '请输入正文', trigger: 'blur' }]
}
}
},
computed: {
id() {
return this.$route.query.id
}
},
methods: {
// 提交
submitForm() {
this.ruleForm.type = this.activeName
this.ruleForm.status = this.status ? 1 : 0
if (this.id) {
updateEssay(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '编辑成功',
type: 'success'
})
this.$router.go(-1)
}
})
} else {
createEssay(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '提交成功',
type: 'success'
})
this.$router.go(-1)
}
})
}
},
// 获取详情
getDetails() {
getDetails({ id: this.id }).then(res => {
this.status = !!parseInt(res.data.status)
this.ruleForm = res.data
})
}
},
mounted() {
if (this.id) {
this.getDetails()
}
}
}
</script>
<style lang="scss" scoped></style>
import httpRequest from '@/utils/axios'
// 获取用户信息
export function getUser() {
return httpRequest.get('/api/passport/account/get-user-info')
}
// 获取首页信息
export function getHomeInfo(params) {
return httpRequest.get('/api/road/v1/frontend/index/index', { params })
}
// 获取页面列表
export function getPageList(params) {
return httpRequest.get('/api/road/v1/frontend/index/page-view', { params })
}
// 获取列表详情
export function getDocDetails(params) {
return httpRequest.get('/api/road/v1/frontend/index/doc-view', { params })
}
const routes = [
// 首页
{
path: '/',
component: () => import('./views/Index.vue')
},
// 列表页
{
path: '/list',
component: () => import('./views/List.vue')
},
// 详情页
{
path: '/details',
component: () => import('./views/Details.vue')
}
]
export { routes }
<template>
<div class="main">
<div class="main_content">
<div class="show_content">
<div class="show_content_img" v-html="data.content"></div>
</div>
</div>
</div>
</template>
<script>
import { getDocDetails } from '../api'
export default {
data() {
return {
data: {}
}
},
methods: {
getDocDetails() {
getDocDetails({ id: this.$route.query.id }).then(res => {
this.data = res.data
})
}
},
mounted() {
this.getDocDetails()
}
}
</script>
<style lang="scss" scoped>
.main {
background: #f7f7f7;
.main_content {
.show_content {
.show_content_img {
padding: .2rem;
// width: 6.9rem;
::v-deep {
p {
font-size: 0.24rem;
}
}
}
}
}
}
::v-deep {
.show_content_img p img {
// width: 6.9rem;
// height: 100%;
width: 100%;
margin: 0 auto;
// border-radius: 0.1rem;
}
}
</style>
<template>
<div class="home-main">
<div class="banner-box">
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
<van-swipe-item
:style="`background-image:url(${item.picture});background-size:cover;`"
v-for="item in homeData.banner_list"
:key="item.id"
@click="goPage(item)"
></van-swipe-item>
</van-swipe>
</div>
<div class="menu-box">
<div @click="goPage(item)" class="item" v-for="item in homeData.menu_list" :key="item.id">
<div class="icon" :style="`background-image: url(${item.picture});`"></div>
<div class="menu-t">{{ item.title }}</div>
</div>
</div>
<div class="main-content" v-for="item in homeData.page_list" :key="item.id">
<div class="title">推荐课程</div>
<div class="course-list">
<div class="item-li" v-for="cItem in item.docs" :key="cItem.id" @click="goDetails(cItem)">
<img :src="cItem.picture" />
<div class="content">
<div class="tit">{{ cItem.title }}</div>
<div class="desc">{{ cItem.remark }}</div>
</div>
</div>
</div>
</div>
<div class="foot-box">
<div class="item">
<div class="icon"></div>
<div class="nav-t">首页</div>
</div>
<div class="item">
<div class="icon"></div>
<div class="nav-t">我的</div>
</div>
</div>
</div>
</template>
<script>
import { Toast } from 'vant'
import { getHomeInfo } from '../api'
export default {
data() {
return {
homeData: {}
}
},
methods: {
getHomeInfo() {
getHomeInfo().then(res => {
this.homeData = res.data
})
},
goPage(row) {
if (row.relation_id) {
switch (row.type) {
case '1':
this.$router.push({ path: '/details', query: { id: row.relation_id } })
break
case '2':
this.$router.push({ path: '/list', query: { id: row.relation_id } })
break
case '3':
window.location.href = row.url
break
}
} else {
Toast('暂未开通')
}
},
goDetails(row) {
this.$router.push({ path: '/details', query: { id: row.id } })
}
},
mounted() {
this.getHomeInfo()
}
}
</script>
<style lang="scss" scoped>
.my-swipe .van-swipe-item {
color: #fff;
text-align: center;
height: 3rem;
// background-color: #39a9ed;
}
.home-main {
background: #f7f7f7;
padding: 0.3rem 0.3rem 0;
.banner-box {
border-radius: 8px;
overflow: hidden;
}
}
.menu-box {
display: flex;
justify-content: space-around;
.item {
padding-top: 0.3rem;
.icon {
width: 0.88rem;
height: 0.88rem;
background-size: 100% 100%;
margin: 0 auto;
}
.menu-t {
font-size: 0.24rem;
line-height: 100%;
text-align: center;
color: #666666;
margin-top: 0.2rem;
}
}
}
.foot-box {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 0.98rem;
background: #fff;
border-top: 1px solid #e6e6e6;
display: flex;
justify-content: space-around;
align-items: center;
.item {
&:nth-child(1) {
.icon {
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/project/pages/highway/road/foot-home.png);
}
&.acitve {
.icon {
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/project/pages/highway/road/foot-home-active.png);
}
}
}
&:nth-child(2) {
.icon {
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/project/pages/highway/road/foot-my.png);
}
&.acitve {
.icon {
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/project/pages/highway/road/foot-my-active.png);
}
}
}
.icon {
width: 0.5rem;
height: 0.5rem;
margin: 0 auto;
background-size: 100% 100%;
}
.nav-t {
text-align: center;
font-size: 0.2rem;
line-height: 100%;
color: #999999;
margin-top: 0.1rem;
}
}
}
.main-content {
padding-top: 0.56rem;
.title {
font-size: 0.3rem;
font-weight: bold;
line-height: 100%;
color: #333333;
padding-left: 0.2rem;
position: relative;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 0.06rem;
height: 0.3rem;
background: #5296f5;
border-radius: 0.03rem;
}
}
.course-list {
padding-bottom: 1.3rem;
.item-li {
background: #ffffff;
border-radius: 0.2rem;
padding: 0.2rem;
display: flex;
margin-top: 0.3rem;
img {
width: 2.2rem;
height: 2.2rem;
border-radius: 0.2rem;
}
.content {
margin-left: 0.28rem;
.tit {
padding-top: 0.2rem;
font-size: 0.3rem;
font-weight: bold;
color: #454545;
}
.desc {
font-size: 0.24rem;
color: #999999;
margin-top: 0.1rem;
}
}
}
}
}
</style>
<template>
<div class="home-main">
<div class="main-content">
<div class="course-list">
<div class="item-li" v-for="item in list" :key="item.id" @click="goPage(item)">
<img :src="item.picture" />
<div class="content">
<div class="tit">{{ item.title }}</div>
<div class="desc">{{ item.remark }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { getPageList } from '../api'
export default {
data() {
return {
list: []
}
},
methods: {
getHomeInfo() {
getPageList({ id: this.$route.query.id }).then(res => {
this.list = res.data.docs
})
},
goPage(row) {
this.$router.push({ path: '/details', query: { id: row.id } })
}
},
mounted() {
this.getHomeInfo()
}
}
</script>
<style lang="scss" scoped>
.home-main {
background: #f7f7f7;
padding: 0.3rem 0.3rem 0;
}
.main-content {
.course-list {
padding-bottom: 1.3rem;
.item-li {
background: #ffffff;
border-radius: 0.2rem;
padding: 0.2rem;
display: flex;
margin-bottom: 0.3rem;
img {
width: 2.2rem;
height: 2.2rem;
border-radius: 0.2rem;
}
.content {
margin-left: 0.28rem;
.tit {
padding-top: 0.2rem;
font-size: 0.3rem;
font-weight: bold;
color: #454545;
}
.desc {
font-size: 0.24rem;
color: #999999;
margin-top: 0.1rem;
}
}
}
}
}
</style>
import httpRequest from '@/utils/axios'
/**
* 新建菜单
*/
export function createMenu(data) {
return httpRequest.post('/api/road/v1/backend/menu/create', data)
}
/**
* 获取应用列表
*/
export function getAppList(params) {
return httpRequest.get('/api/road/v1/backend/menu/list', { params })
}
/**
* 更新菜单
*/
export function updateMenu(data) {
return httpRequest.post('/api/road/v1/backend/menu/update', data)
}
/**
* 获取菜单详情
*/
export function getDetails(params) {
return httpRequest.get('/api/road/v1/backend/menu/view', { params })
}
/**
* 删除菜单
*/
export function deleteMenu(data) {
return httpRequest.post('/api/road/v1/backend/menu/delete', data)
}
// /**
// * 获取应用列表
// */
// export function getAppList(params) {
// return httpRequest.get('/api/register/v1/activity/index', { params })
// }
// /**
// * 新建报名
// */
// export function createRegister(data) {
// return httpRequest.post('/api/register/v1/activity/create', data)
// }
// /**
// * 报名详情
// */
// export function getRegisterDetail(params) {
// return httpRequest.get('/api/register/v1/activity/view', { params })
// }
// /**
// * 更新报名
// */
// export function updateRegister(data) {
// return httpRequest.post('/api/register/v1/activity/update', data)
// }
// /**
// * 删除报名
// */
// export function deleteRegister(data) {
// return httpRequest.post('/api/register/v1/activity/delete', data)
// }
// /**
// * 停止活动
// */
// export function stopRegister(data) {
// return httpRequest.post('/api/register/v1/activity/drop', data)
// }
<template>
<div>
<el-form :disabled="!!$route.query.type" ref="form" :rules="rules" :model="data" label-width="100px">
<el-form-item label="按钮文案:" prop="title">
<el-input v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面展示:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: { type: Object, default: () => {} }
},
data() {
return {
form: {
edit: '',
btnText: ''
},
rules: {
title: [{ required: true, message: '请填写按钮文案', trigger: 'change' }],
desc: [{ required: true, message: '请填写页面内容', trigger: 'change' }]
}
}
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
}
},
mounted() {
console.log(this.data, 'display')
}
}
</script>
<style lang="scss">
.tox-notifications-container {
display: none !important;
}
</style>
<template>
<div class="form-box">
<el-form ref="form" :disabled="!!$route.query.type" :rules="rules" :model="data" size="mini" label-width="150px">
<div class="form-set-info">
<div class="sub-title">信息设置</div>
<el-checkbox-group v-model="checkList" @change="checkboxChange">
<div class="field-list" v-for="(item, index) in fieldList" :key="index">
<div class="field-list_title">{{ item.title }}</div>
<div class="field-list_content">
<el-checkbox
style="margin: 0 90px 10px 10px"
:disabled="cItem.disabled ? cItem.disabled : false"
:label="cItem.key"
v-for="cItem in item.fields"
:key="cItem.key"
>
<div class="checkbox">
{{ cItem.label }}&nbsp;&nbsp;&nbsp;必填:
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="1"
></el-radio
>
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="2"
></el-radio
>
</div>
</el-checkbox>
</div>
</div>
</el-checkbox-group>
</div>
<div class="form-set-pay">
<div class="sub-title">缴费设置</div>
<!--导入功能 新增 -->
<el-form-item label="批量导入功能:">
<el-radio v-model="data.can_import" :label="1">开启</el-radio>
<el-radio v-model="data.can_import" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="缴费功能:">
<el-radio v-model="data.can_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_pay" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_pay">
<el-form-item label="价格:" prop="pay_price">
<el-input style="width: 20%" v-model="data.pay_price"></el-input>
</el-form-item>
<el-form-item label="开票功能:">
<el-radio v-model="data.can_invoice" :label="1">开启</el-radio>
<el-radio v-model="data.can_invoice" :label="0">关闭</el-radio>
</el-form-item>
<!-- 缴费方式 新增-->
<el-form-item label="缴费方式:" prop="pay_type">
<el-select v-model="data.pay_type" multiple>
<el-option v-for="item in payType" :key="item.key" :label="item.value" :value="item.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="线下支付联系方式:" prop="offline_info" v-if="data.pay_type.includes('3')">
<el-input style="width: 20%" v-model="data.offline_info"></el-input>
</el-form-item>
<el-form-item label="线下支付信息:" prop="offline_more_info" v-if="data.pay_type.includes('3')">
<v-editor style="width: 500px" :maxHeight="200" :disabled="!!$route.query.type" v-model="data.offline_more_info"></v-editor>
</el-form-item>
<el-form-item label="单位优惠:">
<el-radio v-model="data.can_company" :label="1">开启</el-radio>
<el-radio v-model="data.can_company" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="单位优惠金额:" prop="company_price" v-if="data.can_company">
<el-input style="width: 20%" v-model="data.company_price"></el-input>
</el-form-item>
<el-form-item label="跳转:">
<el-radio v-model="data.can_jump" :label="1">开启</el-radio>
<el-radio v-model="data.can_jump" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_jump">
<el-form-item label="跳转链接:" prop="jump_url">
<el-input style="width: 20%" v-model="data.jump_url"></el-input>
</el-form-item>
</template>
<el-form-item label="跳过支付:">
<el-radio v-model="data.can_skip_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_skip_pay" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="跳过文案:" prop="skip_pay_title" v-if="!!data.can_skip_pay">
<el-input style="width: 20%" v-model="data.skip_pay_title"></el-input>
</el-form-item>
<el-form-item label="支付平台:" prop="shop_id">
<el-select v-model="data.shop_id" placeholder="请选择">
<el-option v-for="item in shopMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
</template>
</div>
<div class="form-set-page">
<div class="sub-title">页面设置</div>
<el-form-item label="标题:" prop="title">
<el-input style="width: 20%" v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面头部:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: {
type: Object,
default: () => {}
}
},
data() {
return {
payType: [
{ key: '1', value: '微信' },
{ key: '2', value: '支付宝' },
{ key: '3', value: '线下支付' }
],
rules: {
title: { required: true, message: '请填写标题', trigger: 'blur' },
pay_price: [
{ required: true, message: '请填写支付金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('支付金额不能小于等于0元'))
}
}
}
],
jump_url: { required: true, message: '请填写跳转链接', trigger: 'blur' },
shop_id: { required: true, message: '请选择支付平台', trigger: 'change' },
skip_pay_title: { required: true, message: '请填写跳过支付文案', trigger: 'blur' },
pay_type: { required: true, message: '请填选择缴费方式', trigger: 'change' },
company_price: [
{ required: true, message: '请填写单位优惠金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('优惠金额不能小于等于0元'))
}
}
}
]
},
options: [],
checkList: [],
fieldList: [
{
title: '个人信息',
fields: [
{ key: 'name', label: '姓名', required: '1', disabled: true },
{ key: 'mobile', label: '电话', required: '1', disabled: true },
{ key: 'gender', label: '性别', required: '1' },
{ key: 'email', label: '邮箱', required: '1' },
{ key: 'company', label: '公司', required: '1' },
{ key: 'position', label: '职位', required: '1' },
{ key: 'number', label: '编号', required: '1' },
{ key: 'country', label: '国籍', required: '1' },
{ key: 'provinces', label: '省份', required: '1' },
{ key: 'city', label: '城市', required: '1' },
{ key: 'address', label: '地址', required: '1' },
{ key: 'fixed_telephone', label: '固话', required: '1' },
{ key: 'industry', label: '行业', required: '1' },
{ key: 'id_number', label: '身份证号码', required: '1' }
]
},
{
title: '社交信息',
fields: [
{ key: 'wechat', label: '微信', required: '1' },
{ key: 'qq', label: 'QQ', required: '1' },
{ key: 'ding', label: '钉钉', required: '1' },
{ key: 'weibo', label: '微博', required: '1' }
]
},
{
title: '入住信息',
fields: [
{ key: 'check_in_time', label: '入住时间', required: '1' },
{ key: 'check_out_time', label: '离店时间', required: '1' },
{ key: 'room_type', label: '房型', required: '1' },
{ key: 'breakfast', label: '早餐', required: '1' }
]
}
]
}
},
computed: {
shopMap() {
return this.$store.state.commonMap.details_shop_map
},
payTypeMap() {
return this.data.pay_type
}
},
created() {},
mounted() {
this.setInfoFields()
},
methods: {
// 信息设置数据回显
setInfoFields() {
this.fieldList = this.fieldList.reduce((a, b) => {
b.fields.map(item => {
const findData = this.data.user_fields.find(fData => fData.key === item.key)
if (findData) {
this.checkList.push(findData.key)
item.required = findData.required ? '1' : '2'
}
return item
})
a.push(b)
return a
}, [])
},
// 信息设置选择后 吧选择的编程后台需要的数据
checkboxChange() {
this.data.user_fields = this.fieldList.reduce((a, b) => {
b.fields.forEach(item => {
const findData = this.checkList.find(fData => fData === item.key)
if (findData) {
a.push({ key: item.key, required: !!(item.required === '1'), enable_edit: true })
}
})
return a
}, [])
this.data.pay_type = this.data.pay_type.toString()
},
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
this.checkboxChange()
flag = true
}
})
return flag
}
}
}
</script>
<style lang="scss" scoped>
.sub-title {
line-height: 100%;
font-size: 16px;
font-weight: bold;
color: #333333;
border-left: 3px solid rgba(184, 1, 64, 1);
padding-left: 7px;
margin-bottom: 25px;
}
.form-box {
padding-top: 15px;
}
::v-deep {
.form-set-info {
.el-form-item__content {
display: flex;
align-items: center;
}
.el-icon-remove-outline {
font-size: 22px;
margin-left: 10px;
color: rgba(214, 214, 214, 1);
cursor: pointer;
}
.required {
margin-left: 15px;
}
}
}
.form-set-pay {
border-bottom: 1px solid #d6d6d6;
padding: 25px 0 15px;
}
.form-set-page {
padding: 25px 0 15px;
border-bottom: 1px solid #d6d6d6;
}
.form-set-info {
border-bottom: 1px solid #d6d6d6;
padding-bottom: 30px;
.field-list {
margin-bottom: 30px;
.field-list_title {
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
}
.field-list_content {
padding-top: 15px;
.checkbox {
display: flex;
align-items: center;
}
}
}
}
</style>
<template>
<div>
<el-form ref="form" :disabled="!!$route.query.type" :inline="true" :rules="rules" :model="form">
<el-form-item label="页面标题:" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="活动名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="人数限制:" prop="max_number">
<el-input v-model="form.max_number"></el-input>
</el-form-item>
<el-form-item label="关联项目:" prop="project_id">
<el-select v-model="form.project_id" placeholder="请选择">
<el-option v-for="item in projectMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="活动开始时间:" prop="activity_time">
<el-date-picker
v-model="form.activity_time"
type="datetime"
@change="activityDateChange"
placeholder="选择日期时间"
:picker-options="pickerOptions"
>
</el-date-picker>
</el-form-item>
<el-form-item label="报名时间:" prop="time">
<el-date-picker
@change="dateChange"
v-model="form.time"
type="datetimerange"
range-separator="至"
start-placeholder="报名开始日期"
end-placeholder="报名结束日期"
>
</el-date-picker>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
form: { type: Object, default: () => {} }
},
data() {
return {
rules: {
title: { required: true, message: '请填写页面标题', trigger: 'blur' },
name: { required: true, message: '请填写活动标题', trigger: 'blur' },
max_number: [
{ required: true, message: '请填写最大参与人数', trigger: 'blur' },
{
trigger: 'blur',
min: 1,
message: '最大人数限制不能小于1人',
validator(rule, value, callback) {
if (parseInt(Number(value)) && Number(value) >= 1) {
callback()
} else {
callback(new Error('最大人数限制不能小于1人'))
}
}
}
],
project_id: { required: true, message: '请关联项目', trigger: 'change' },
time: { required: true, message: '请选择时间', trigger: 'change' },
activity_time: { required: true, message: '请选择时间', trigger: 'change' }
},
pickerOptions: {
disabledDate(v) {
return v.getTime() < new Date().getTime() - 86400000
}
}
}
},
computed: {
projectMap() {
return this.$store.state.commonMap.project_map || {}
}
},
mounted() {
console.log(this.form)
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
},
// 日期改变的时候。吧日期转成后台需要的格式
dateChange(date) {
this.form.start_time = this.setDate(date[0])
this.form.end_time = this.setDate(date[1])
},
setDate(val) {
const d = new Date(val)
const date = `${d.getFullYear()}-${this.toDo(d.getMonth() + 1)}-${this.toDo(d.getDate())} ${this.toDo(
d.getHours()
)}:${this.toDo(d.getMinutes())}:${this.toDo(d.getSeconds())}`
return date
},
toDo(n) {
return n < 10 ? `0${n}` : n
},
activityDateChange() {
this.form.activity_time = this.setDate(this.form.activity_time)
}
}
}
</script>
<style lang="scss" scoped></style>
import AppLayout from '@/components/layout/Index.vue'
const routes = [
{
path: '/menu',
component: AppLayout,
children: [
{ path: 'list', component: () => import('./views/List.vue') },
{ path: 'Update', component: () => import('./views/Update.vue') }
]
}
]
export { routes }
<template>
<app-card class="register-box">
<app-list v-bind="tableOptions" ref="list">
<div class="line"></div>
<div class="btn-box">
<el-button type="primary" @click="$router.push({ path: '/menu/update' })">新建菜单</el-button>
</div>
<template v-slot:filter-time>
<el-date-picker
v-model="filterDate"
@change="changeDate"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</template>
<template v-slot:picture="{ row }">
<div :style="`background-image:url(${row.picture});background-size: cover;width:50px;height:40px;`"></div>
</template>
<template v-slot:release-status="{ row }">
<el-switch v-model="row.status" @change="updateStatus(row)"> </el-switch>
</template>
<template v-slot:sort-select="{ row }">
<el-select v-model="row.sort" placeholder="请选择" @change="updateStatus(row)">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</template>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleEdit(row)">编辑</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
</app-list>
</app-card>
</template>
<script>
// 接口
import { getAppList, updateMenu, deleteMenu } from '../api'
export default {
data() {
const count = []
for (let i = 0; i < 100; i++) {
count.push({ value: i, options: i })
}
return {
value1: '',
filterDate: '',
options: count,
createdStart: '',
createdEnd: ''
}
},
computed: {
// 列表配置
tableOptions() {
return {
limit: 10,
remote: {
httpRequest: getAppList,
params: {
title: '',
status: '',
created_time_start: this.createdStart,
created_time_end: this.createdEnd
},
callback: res => {
res.map(item => {
item.status = !!parseInt(item.status)
return item
})
return res
}
},
filters: [
{
type: 'input',
prop: 'title',
label: '标题:'
},
{
type: 'select',
prop: 'status',
label: '发布状态:',
options: [
{ value: '0', label: '未发布' },
{ value: '1', label: '已发布' }
]
},
{
slots: 'filter-time',
label: '创建时间:'
}
],
columns: [
{ label: 'id', prop: 'id', align: 'center' },
{ label: '菜单图标', slots: 'picture', align: 'center', width: '50px' },
{ label: '菜单名称', prop: 'title', align: 'center' },
{ label: '备注', prop: 'comment', align: 'center' },
{
label: '发布状态',
slots: 'release-status',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '排序', slots: 'sort-select', align: 'center' },
{ label: '操作', slots: 'table-x', align: 'center' }
]
}
}
},
methods: {
// 时间搜索
changeDate() {
if (this.filterDate) {
this.createdStart = this.filterDate[0]
this.createdEnd = this.filterDate[1]
} else {
this.createdStart = ''
this.createdEnd = ''
// this.$refs.list.refetch(true)
}
},
// 更新发布状态
updateStatus(row) {
const params = row
params.status = row.status ? '1' : '0'
updateMenu(row).then(res => {
if (res.code === 0) {
this.$message({
message: '修改成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
},
handleEdit(row) {
this.$router.push({ path: '/menu/update', query: { id: row.id } })
},
handleDelete(row) {
deleteMenu({ id: row.id }).then(res => {
if (res.code === 0) {
this.$message({
message: '删除成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
}
}
}
</script>
<style lang="scss">
.register-box {
.el-form-item {
margin-right: 20px !important;
}
.line {
// border-top: 1px solid #D6D6D6;
height: 1px;
background: #d6d6d6;
margin: 8px 0 23px;
box-sizing: border-box;
}
.btn-box {
margin-bottom: 16px;
}
}
</style>
<template>
<div class="create-box">
<app-card :title="!$route.query.id ? '新建菜单' : '编辑菜单'">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
style="width: 40%; margin: 0 auto"
>
<el-form-item label="菜单名称" prop="title">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="ruleForm.comment"></el-input>
</el-form-item>
<el-form-item label="菜单图标" prop="picture">
<upload-image v-model="ruleForm.picture"></upload-image>
</el-form-item>
<el-form-item label="是否启用" prop="status">
<el-switch v-model="status"></el-switch>
</el-form-item>
<el-form-item label="关联选择">
<el-button type="primary" @click="drawer = true">点击选择</el-button>
</el-form-item>
<el-form-item>
<div style="padding-top: 20px">
<el-button type="primary" @click="submitForm">确认</el-button>
<el-button @click="drawer = true">取消</el-button>
</div>
</el-form-item>
</el-form>
</app-card>
<el-drawer size="40%" :visible.sync="drawer" :direction="direction">
<div style="padding: 0 20px">
<el-tabs v-model="activeName">
<el-tab-pane label="关联图文" name="1"></el-tab-pane>
<el-tab-pane label="关联页面" name="2"></el-tab-pane>
<el-tab-pane label="跳转链接" name="3"></el-tab-pane>
</el-tabs>
</div>
</el-drawer>
</div>
</template>
<script>
import UploadImage from '@/components/upload/UploadImage.vue'
import { createMenu, getDetails, updateMenu } from '../api'
export default {
components: {
UploadImage
},
data() {
return {
activeName: '1',
status: true,
drawer: false,
direction: 'rtl',
ruleForm: {
title: '',
url: '',
picture: '',
type: '',
status: true,
relations_id: '',
comment: ''
},
rules: {
title: [{ required: true, message: '请填写菜单名称', trigger: 'blur' }],
picture: [{ required: true, message: '请上传banner', trigger: 'blur' }],
status: [{ required: true, message: '', trigger: 'blur' }]
}
}
},
computed: {
id() {
return this.$route.query.id
}
},
methods: {
// 提交
submitForm() {
this.ruleForm.type = this.activeName
this.ruleForm.status = this.status ? 1 : 0
if (this.id) {
updateMenu(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '编辑成功',
type: 'success'
})
this.$router.go(-1)
}
})
} else {
createMenu(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '提交成功',
type: 'success'
})
this.$router.go(-1)
}
})
}
},
// 获取详情
getDetails() {
getDetails({ id: this.id }).then(res => {
this.status = !!parseInt(res.data.status)
this.ruleForm = res.data
})
}
},
mounted() {
if (this.id) {
this.getDetails()
}
}
}
</script>
<style lang="scss" scoped></style>
import httpRequest from '@/utils/axios'
/**
* 新建页面
*/
export function createPages(data) {
return httpRequest.post('/api/road/v1/backend/page/create', data)
}
/**
* 获取应用列表
*/
export function getAppList(params) {
return httpRequest.get('/api/road/v1/backend/page/list', { params })
}
/**
* 更新页面
*/
export function updatePages(data) {
return httpRequest.post('/api/road/v1/backend/page/update', data)
}
/**
* 获取页面详情
*/
export function getDetails(params) {
return httpRequest.get('/api/road/v1/backend/page/view', { params })
}
/**
* 删除页面
*/
export function deletePages(data) {
return httpRequest.post('/api/road/v1/backend/page/delete', data)
}
// /**
// * 获取应用列表
// */
// export function getAppList(params) {
// return httpRequest.get('/api/register/v1/activity/index', { params })
// }
// /**
// * 新建报名
// */
// export function createRegister(data) {
// return httpRequest.post('/api/register/v1/activity/create', data)
// }
// /**
// * 报名详情
// */
// export function getRegisterDetail(params) {
// return httpRequest.get('/api/register/v1/activity/view', { params })
// }
// /**
// * 更新报名
// */
// export function updateRegister(data) {
// return httpRequest.post('/api/register/v1/activity/update', data)
// }
// /**
// * 删除报名
// */
// export function deleteRegister(data) {
// return httpRequest.post('/api/register/v1/activity/delete', data)
// }
// /**
// * 停止活动
// */
// export function stopRegister(data) {
// return httpRequest.post('/api/register/v1/activity/drop', data)
// }
<template>
<div>
<el-form :disabled="!!$route.query.type" ref="form" :rules="rules" :model="data" label-width="100px">
<el-form-item label="按钮文案:" prop="title">
<el-input v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面展示:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: { type: Object, default: () => {} }
},
data() {
return {
form: {
edit: '',
btnText: ''
},
rules: {
title: [{ required: true, message: '请填写按钮文案', trigger: 'change' }],
desc: [{ required: true, message: '请填写页面内容', trigger: 'change' }]
}
}
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
}
},
mounted() {
console.log(this.data, 'display')
}
}
</script>
<style lang="scss">
.tox-notifications-container {
display: none !important;
}
</style>
<template>
<div class="form-box">
<el-form ref="form" :disabled="!!$route.query.type" :rules="rules" :model="data" size="mini" label-width="150px">
<div class="form-set-info">
<div class="sub-title">信息设置</div>
<el-checkbox-group v-model="checkList" @change="checkboxChange">
<div class="field-list" v-for="(item, index) in fieldList" :key="index">
<div class="field-list_title">{{ item.title }}</div>
<div class="field-list_content">
<el-checkbox
style="margin: 0 90px 10px 10px"
:disabled="cItem.disabled ? cItem.disabled : false"
:label="cItem.key"
v-for="cItem in item.fields"
:key="cItem.key"
>
<div class="checkbox">
{{ cItem.label }}&nbsp;&nbsp;&nbsp;必填:
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="1"
></el-radio
>
<el-radio
@change="checkboxChange"
v-model="cItem.required"
:disabled="cItem.disabled ? cItem.disabled : false"
label="2"
></el-radio
>
</div>
</el-checkbox>
</div>
</div>
</el-checkbox-group>
</div>
<div class="form-set-pay">
<div class="sub-title">缴费设置</div>
<!--导入功能 新增 -->
<el-form-item label="批量导入功能:">
<el-radio v-model="data.can_import" :label="1">开启</el-radio>
<el-radio v-model="data.can_import" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="缴费功能:">
<el-radio v-model="data.can_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_pay" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_pay">
<el-form-item label="价格:" prop="pay_price">
<el-input style="width: 20%" v-model="data.pay_price"></el-input>
</el-form-item>
<el-form-item label="开票功能:">
<el-radio v-model="data.can_invoice" :label="1">开启</el-radio>
<el-radio v-model="data.can_invoice" :label="0">关闭</el-radio>
</el-form-item>
<!-- 缴费方式 新增-->
<el-form-item label="缴费方式:" prop="pay_type">
<el-select v-model="data.pay_type" multiple>
<el-option v-for="item in payType" :key="item.key" :label="item.value" :value="item.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="线下支付联系方式:" prop="offline_info" v-if="data.pay_type.includes('3')">
<el-input style="width: 20%" v-model="data.offline_info"></el-input>
</el-form-item>
<el-form-item label="线下支付信息:" prop="offline_more_info" v-if="data.pay_type.includes('3')">
<v-editor style="width: 500px" :maxHeight="200" :disabled="!!$route.query.type" v-model="data.offline_more_info"></v-editor>
</el-form-item>
<el-form-item label="单位优惠:">
<el-radio v-model="data.can_company" :label="1">开启</el-radio>
<el-radio v-model="data.can_company" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="单位优惠金额:" prop="company_price" v-if="data.can_company">
<el-input style="width: 20%" v-model="data.company_price"></el-input>
</el-form-item>
<el-form-item label="跳转:">
<el-radio v-model="data.can_jump" :label="1">开启</el-radio>
<el-radio v-model="data.can_jump" :label="0">关闭</el-radio>
</el-form-item>
<template v-if="!!data.can_jump">
<el-form-item label="跳转链接:" prop="jump_url">
<el-input style="width: 20%" v-model="data.jump_url"></el-input>
</el-form-item>
</template>
<el-form-item label="跳过支付:">
<el-radio v-model="data.can_skip_pay" :label="1">开启</el-radio>
<el-radio v-model="data.can_skip_pay" :label="0">关闭</el-radio>
</el-form-item>
<el-form-item label="跳过文案:" prop="skip_pay_title" v-if="!!data.can_skip_pay">
<el-input style="width: 20%" v-model="data.skip_pay_title"></el-input>
</el-form-item>
<el-form-item label="支付平台:" prop="shop_id">
<el-select v-model="data.shop_id" placeholder="请选择">
<el-option v-for="item in shopMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
</template>
</div>
<div class="form-set-page">
<div class="sub-title">页面设置</div>
<el-form-item label="标题:" prop="title">
<el-input style="width: 20%" v-model="data.title"></el-input>
</el-form-item>
<el-form-item label="页面头部:" prop="desc">
<v-editor :disabled="!!$route.query.type" v-model="data.desc"></v-editor>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
data: {
type: Object,
default: () => {}
}
},
data() {
return {
payType: [
{ key: '1', value: '微信' },
{ key: '2', value: '支付宝' },
{ key: '3', value: '线下支付' }
],
rules: {
title: { required: true, message: '请填写标题', trigger: 'blur' },
pay_price: [
{ required: true, message: '请填写支付金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('支付金额不能小于等于0元'))
}
}
}
],
jump_url: { required: true, message: '请填写跳转链接', trigger: 'blur' },
shop_id: { required: true, message: '请选择支付平台', trigger: 'change' },
skip_pay_title: { required: true, message: '请填写跳过支付文案', trigger: 'blur' },
pay_type: { required: true, message: '请填选择缴费方式', trigger: 'change' },
company_price: [
{ required: true, message: '请填写单位优惠金额', trigger: 'blur' },
{
trigger: 'blur',
min: 0,
validator(rule, value, callback) {
if (Number(value) > 0) {
callback()
} else {
callback(new Error('优惠金额不能小于等于0元'))
}
}
}
]
},
options: [],
checkList: [],
fieldList: [
{
title: '个人信息',
fields: [
{ key: 'name', label: '姓名', required: '1', disabled: true },
{ key: 'mobile', label: '电话', required: '1', disabled: true },
{ key: 'gender', label: '性别', required: '1' },
{ key: 'email', label: '邮箱', required: '1' },
{ key: 'company', label: '公司', required: '1' },
{ key: 'position', label: '职位', required: '1' },
{ key: 'number', label: '编号', required: '1' },
{ key: 'country', label: '国籍', required: '1' },
{ key: 'provinces', label: '省份', required: '1' },
{ key: 'city', label: '城市', required: '1' },
{ key: 'address', label: '地址', required: '1' },
{ key: 'fixed_telephone', label: '固话', required: '1' },
{ key: 'industry', label: '行业', required: '1' },
{ key: 'id_number', label: '身份证号码', required: '1' }
]
},
{
title: '社交信息',
fields: [
{ key: 'wechat', label: '微信', required: '1' },
{ key: 'qq', label: 'QQ', required: '1' },
{ key: 'ding', label: '钉钉', required: '1' },
{ key: 'weibo', label: '微博', required: '1' }
]
},
{
title: '入住信息',
fields: [
{ key: 'check_in_time', label: '入住时间', required: '1' },
{ key: 'check_out_time', label: '离店时间', required: '1' },
{ key: 'room_type', label: '房型', required: '1' },
{ key: 'breakfast', label: '早餐', required: '1' }
]
}
]
}
},
computed: {
shopMap() {
return this.$store.state.commonMap.details_shop_map
},
payTypeMap() {
return this.data.pay_type
}
},
created() {},
mounted() {
this.setInfoFields()
},
methods: {
// 信息设置数据回显
setInfoFields() {
this.fieldList = this.fieldList.reduce((a, b) => {
b.fields.map(item => {
const findData = this.data.user_fields.find(fData => fData.key === item.key)
if (findData) {
this.checkList.push(findData.key)
item.required = findData.required ? '1' : '2'
}
return item
})
a.push(b)
return a
}, [])
},
// 信息设置选择后 吧选择的编程后台需要的数据
checkboxChange() {
this.data.user_fields = this.fieldList.reduce((a, b) => {
b.fields.forEach(item => {
const findData = this.checkList.find(fData => fData === item.key)
if (findData) {
a.push({ key: item.key, required: !!(item.required === '1'), enable_edit: true })
}
})
return a
}, [])
this.data.pay_type = this.data.pay_type.toString()
},
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
this.checkboxChange()
flag = true
}
})
return flag
}
}
}
</script>
<style lang="scss" scoped>
.sub-title {
line-height: 100%;
font-size: 16px;
font-weight: bold;
color: #333333;
border-left: 3px solid rgba(184, 1, 64, 1);
padding-left: 7px;
margin-bottom: 25px;
}
.form-box {
padding-top: 15px;
}
::v-deep {
.form-set-info {
.el-form-item__content {
display: flex;
align-items: center;
}
.el-icon-remove-outline {
font-size: 22px;
margin-left: 10px;
color: rgba(214, 214, 214, 1);
cursor: pointer;
}
.required {
margin-left: 15px;
}
}
}
.form-set-pay {
border-bottom: 1px solid #d6d6d6;
padding: 25px 0 15px;
}
.form-set-page {
padding: 25px 0 15px;
border-bottom: 1px solid #d6d6d6;
}
.form-set-info {
border-bottom: 1px solid #d6d6d6;
padding-bottom: 30px;
.field-list {
margin-bottom: 30px;
.field-list_title {
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
}
.field-list_content {
padding-top: 15px;
.checkbox {
display: flex;
align-items: center;
}
}
}
}
</style>
<template>
<div>
<el-form ref="form" :disabled="!!$route.query.type" :inline="true" :rules="rules" :model="form">
<el-form-item label="页面标题:" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="活动名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="人数限制:" prop="max_number">
<el-input v-model="form.max_number"></el-input>
</el-form-item>
<el-form-item label="关联项目:" prop="project_id">
<el-select v-model="form.project_id" placeholder="请选择">
<el-option v-for="item in projectMap" :key="item.key" :label="item.value" :value="item.key"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="活动开始时间:" prop="activity_time">
<el-date-picker
v-model="form.activity_time"
type="datetime"
@change="activityDateChange"
placeholder="选择日期时间"
:picker-options="pickerOptions"
>
</el-date-picker>
</el-form-item>
<el-form-item label="报名时间:" prop="time">
<el-date-picker
@change="dateChange"
v-model="form.time"
type="datetimerange"
range-separator="至"
start-placeholder="报名开始日期"
end-placeholder="报名结束日期"
>
</el-date-picker>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
form: { type: Object, default: () => {} }
},
data() {
return {
rules: {
title: { required: true, message: '请填写页面标题', trigger: 'blur' },
name: { required: true, message: '请填写活动标题', trigger: 'blur' },
max_number: [
{ required: true, message: '请填写最大参与人数', trigger: 'blur' },
{
trigger: 'blur',
min: 1,
message: '最大人数限制不能小于1人',
validator(rule, value, callback) {
if (parseInt(Number(value)) && Number(value) >= 1) {
callback()
} else {
callback(new Error('最大人数限制不能小于1人'))
}
}
}
],
project_id: { required: true, message: '请关联项目', trigger: 'change' },
time: { required: true, message: '请选择时间', trigger: 'change' },
activity_time: { required: true, message: '请选择时间', trigger: 'change' }
},
pickerOptions: {
disabledDate(v) {
return v.getTime() < new Date().getTime() - 86400000
}
}
}
},
computed: {
projectMap() {
return this.$store.state.commonMap.project_map || {}
}
},
mounted() {
console.log(this.form)
},
methods: {
submitForm() {
let flag = false
this.$refs.form.validate(valid => {
if (valid) {
flag = true
}
})
return flag
},
// 日期改变的时候。吧日期转成后台需要的格式
dateChange(date) {
this.form.start_time = this.setDate(date[0])
this.form.end_time = this.setDate(date[1])
},
setDate(val) {
const d = new Date(val)
const date = `${d.getFullYear()}-${this.toDo(d.getMonth() + 1)}-${this.toDo(d.getDate())} ${this.toDo(
d.getHours()
)}:${this.toDo(d.getMinutes())}:${this.toDo(d.getSeconds())}`
return date
},
toDo(n) {
return n < 10 ? `0${n}` : n
},
activityDateChange() {
this.form.activity_time = this.setDate(this.form.activity_time)
}
}
}
</script>
<style lang="scss" scoped></style>
import AppLayout from '@/components/layout/Index.vue'
const routes = [
{
path: '/pages',
component: AppLayout,
children: [
{ path: 'list', component: () => import('./views/List.vue') },
{ path: 'Update', component: () => import('./views/Update.vue') }
]
}
]
export { routes }
<template>
<app-card class="register-box">
<app-list v-bind="tableOptions" ref="list">
<div class="line"></div>
<div class="btn-box">
<el-button type="primary" @click="$router.push({ path: '/pages/update' })">新建页面</el-button>
</div>
<template v-slot:filter-time>
<el-date-picker
v-model="filterDate"
@change="changeDate"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</template>
<template v-slot:picture="{ row }">
<div :style="`background-image:url(${row.picture});background-size: cover;width:50px;height:40px;`"></div>
</template>
<template v-slot:release-status="{ row }">
<el-switch v-model="row.status" @change="updateStatus(row)"> </el-switch>
</template>
<template v-slot:sort-select="{ row }">
<el-select v-model="row.sort" placeholder="请选择" @change="updateStatus(row)">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</template>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleEdit(row)">编辑</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
</app-list>
</app-card>
</template>
<script>
// 接口
import { getAppList, updatePages, deletePages } from '../api'
export default {
data() {
const count = []
for (let i = 0; i < 100; i++) {
count.push({ value: i, options: i })
}
return {
value1: '',
filterDate: '',
options: count,
createdStart: '',
createdEnd: ''
}
},
computed: {
// 列表配置
tableOptions() {
return {
limit: 10,
remote: {
httpRequest: getAppList,
params: {
title: '',
status: '',
created_time_start: this.createdStart,
created_time_end: this.createdEnd
},
callback: res => {
res.map(item => {
item.status = !!parseInt(item.status)
return item
})
return res
}
},
filters: [
{
type: 'input',
prop: 'title',
label: '标题:'
},
{
type: 'select',
prop: 'status',
label: '发布状态:',
options: [
{ value: '0', label: '未发布' },
{ value: '1', label: '已发布' }
]
},
{
slots: 'filter-time',
label: '创建时间:'
}
],
columns: [
{ label: 'id', prop: 'id', align: 'center' },
{ label: '页面类型', prop: 'type_name', align: 'center' },
{ label: '页面模板', prop: 'layout_name', align: 'center' },
{ label: '标题', prop: 'title', align: 'center' },
{
label: '发布状态',
slots: 'release-status',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '排序', slots: 'sort-select', align: 'center' },
{ label: '操作', slots: 'table-x', align: 'center' }
]
}
}
},
methods: {
// 时间搜索
changeDate() {
if (this.filterDate) {
this.createdStart = this.filterDate[0]
this.createdEnd = this.filterDate[1]
} else {
this.createdStart = ''
this.createdEnd = ''
// this.$refs.list.refetch(true)
}
},
// 更新发布状态
updateStatus(row) {
const params = row
params.status = row.status ? '1' : '0'
updatePages(row).then(res => {
if (res.code === 0) {
this.$message({
message: '修改成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
},
handleEdit(row) {
this.$router.push({ path: '/pages/update', query: { id: row.id } })
},
handleDelete(row) {
deletePages({ id: row.id }).then(res => {
if (res.code === 0) {
this.$message({
message: '删除成功',
type: 'success'
})
this.$refs.list.refetch(true)
}
})
}
}
}
</script>
<style lang="scss">
.register-box {
.el-form-item {
margin-right: 20px !important;
}
.line {
// border-top: 1px solid #D6D6D6;
height: 1px;
background: #d6d6d6;
margin: 8px 0 23px;
box-sizing: border-box;
}
.btn-box {
margin-bottom: 16px;
}
}
</style>
<template>
<div class="create-box">
<app-card :title="!$route.query.id ? '新建页面' : '编辑页面'">
<el-form
:model="ruleForm"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
style="width: 50%; margin: 0 auto"
>
<el-form-item label="页面类型">
<el-radio-group v-model="ruleForm.type">
<el-radio label="1">首页展示区</el-radio>
<el-radio label="2">二级列表页</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="页面模板">
<el-radio-group v-model="ruleForm.layout">
<el-radio label="1">左图又文字</el-radio>
<el-radio label="2">上图下文</el-radio>
<el-radio label="3">文本</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="页面名称" prop="title">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item>
<div style="padding-top: 20px">
<el-button type="primary" @click="submitForm">确认</el-button>
<el-button @click="drawer = true">取消</el-button>
</div>
</el-form-item>
</el-form>
</app-card>
</div>
</template>
<script>
import { createPages, getDetails, updatePages } from '../api'
export default {
data() {
return {
ruleForm: {
type: '1',
layout: '1',
title: ''
}
}
},
computed: {
id() {
return this.$route.query.id
}
},
methods: {
// 提交
submitForm() {
if (this.id) {
updatePages(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '编辑成功',
type: 'success'
})
this.$router.go(-1)
}
})
} else {
createPages(this.ruleForm).then(res => {
if (res.code === 0) {
this.$message({
message: '提交成功',
type: 'success'
})
this.$router.go(-1)
}
})
}
},
// 获取详情
getDetails() {
getDetails({ id: this.id }).then(res => {
this.status = !!parseInt(res.data.status)
this.ruleForm = res.data
})
}
},
mounted() {
if (this.id) {
this.getDetails()
}
}
}
</script>
<style lang="scss" scoped></style>
......@@ -3,7 +3,7 @@ import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{ path: '*', redirect: '/banner/list' }]
const routes = [{ path: '*', redirect: '/' }]
const router = new VueRouter({
mode: 'history',
......
import Vue from 'vue'
import Vuex from 'vuex'
import { getUser, logout, getPermissions, getCommonMap } from '@/api/base'
import { getUser, logout, getAllSetting } from '@/api/base'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
user: {},
permissions: [],
commonMap: {} // 权限列表
stepIndex: 0,
stepResult: [],
allSettings: {}
},
mutations: {
setUser(state, user) {
state.user = user
},
setPermissions(state, permissions) {
state.permissions = permissions
saveStepIndex(state, stepIndex) {
state.stepIndex = stepIndex
},
setCommonMap(state, commonMap) {
state.commonMap = commonMap
setStepResult(state, stepResult) {
state.stepResult = stepResult
},
setAllSettings(state, allSettings) {
state.allSettings = allSettings
}
},
actions: {
// 获取所有项目列表
getCommonMap({ commit }) {
getCommonMap().then(res => {
const data = res.data
// 所有项目列表
commit('setCommonMap', data)
})
},
getPermissions({ commit }) {
getPermissions({ type: 2 }).then(res => {
if (res.data && res.data.items) {
commit('setPermissions', res.data.items)
}
})
},
// 获取用户信息
getUser({ commit }) {
getUser().then(response => {
commit('setUser', response)
commit('setUser', response.data)
})
},
// 退出登录
......@@ -54,6 +44,8 @@ const store = new Vuex.Store({
const isLogin = await getUser()
.then(response => {
if (response.code === 0) {
window.localStorage.userInfo = JSON.stringify(response.data)
store.dispatch('getAllSetting')
commit('setUser', response.data)
return true
} else {
......@@ -66,12 +58,14 @@ const store = new Vuex.Store({
return false
})
return isLogin
},
// 获取所有项目列表
getAllSetting({ commit }) {
getAllSetting().then(res => {
window.localStorage.allSetting = JSON.stringify(res.data)
commit('setAllSettings', res.data)
})
}
}
})
// 获取权限列表
// store.dispatch('getPermissions')
// 初始化获取项目列表
// store.dispatch('getCommonMap')
export default store
import axios from 'axios'
// import queryString from 'query-string'
import qs from 'qs'
import { Message } from 'element-ui'
import router from '../router'
// import store from '../store'
import qs from 'qs'
const httpRequest = axios.create({
timeout: 60000,
......@@ -13,20 +14,6 @@ const httpRequest = axios.create({
// 请求拦截
httpRequest.interceptors.request.use(
function (config) {
// 权限接口单独签名
// https://gitlab.ezijing.com/root/api-documents/-/blob/master/ezijing_permissions/%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81.md
if (/^\/api\/permissions/.test(config.url)) {
// 默认参数
const defaultHeaders = {
timestamp: parseInt(Date.now() / 1000),
nonce: Math.random().toString(36).slice(-8),
'secret-id': import.meta.env.VITE_SECRET_ID,
'secret-key': import.meta.env.VITE_SECRET_KEY,
signature: 'UG7wBenexQhiuD2wpCwuxkU0jqcj006d'
}
config.headers = Object.assign(config.headers, defaultHeaders)
}
if (config.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
config.data = qs.stringify(config.data)
}
......@@ -48,35 +35,43 @@ httpRequest.interceptors.request.use(
httpRequest.interceptors.response.use(
function (response) {
const { data } = response
// 正常返回
if (data.code === 0 || !Object.keys(data).includes('code')) {
return data
}
// 未登录
if (data.code === 4001) {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(window.location.href)}`
}
// 没有权限
if (data.code === 4008) {
router.push('/401')
if (data.code && data.code !== 999) {
// 未登录
if (data.code === 4001) {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}`
}
// 未登录
if (data.code === 1) {
// window.location.href = `${import.meta.env.VITE_LOGIN_URL}`
return data
}
// 没有权限
if (data.code === 4008 || data.code === 5018) {
router.push('/401')
}
// 题库分类修改
if (data.code === 403) {
Message({ message: '没有操作权限', type: 'error' })
return data
}
Message({ message: data.message, type: 'error' })
return Promise.reject(data)
}
Message({ message: data.message, type: 'error' })
return Promise.reject(data)
return data
},
function (error) {
if (error.response) {
const { status, message } = error.response.data
// 未登录
if (status === 403) {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(window.location.href)}`
window.location.href = `${import.meta.env.VITE_LOGIN_URL}`
} else {
Message.error(message || error.response.data)
}
return Promise.reject(error.response)
} else {
console.log(error)
}
return Promise.reject(error)
return Promise.reject(error.response || error)
}
)
......
import store from '@/store'
const UA = navigator.userAgent
const isMobile = /iphone/i.test(UA) || (/android/i.test(UA) && /mobile/i.test(UA))
const isIe = window.ActiveXObject || 'ActiveXObject' in window
// const isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime)
// let chromeVersion = 0
// if (isChrome) {
// const temp = UA.match(/Chrome\/([\d.]+)/)
// chromeVersion = temp ? parseFloat(temp[1]) : 0
// }
// const notSupport = !isMobile && (isIe || (isChrome && chromeVersion < 70))
const notSupport = !isMobile && isIe
// https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
export default async function (to, from, next) {
// 浏览器不支持
if (notSupport && to.name !== 'browser') {
next({ path: '/browser' })
return
}
// 登录白名单
const whiteList = []
if (whiteList.includes(to.path)) {
next()
return
}
const isLogin = store.state.user.id || (await store.dispatch('checkLogin'))
if (!isLogin) {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(window.location.href)}`
return
}
next()
}
const allFormList = [
{
type: 'input',
name: '姓名',
placeholder: '请输入姓名',
required: true,
key: 'name',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '电话',
placeholder: '请输入电话',
required: true,
key: 'mobile',
value: '',
enable_edit: true,
inputType: 'tel',
trigger: 'onBlur',
msg: '请输入正确的手机号',
pattern: /^1(3|4|7|5|8)([0-9]{9})/
},
{
type: 'radio',
name: '性别',
key: 'gender',
required: true,
value: '0',
enable_edit: true,
optionList: [
{ id: '0', option: '未知' },
{ id: '1', option: '男' },
{ id: '2', option: '女' }
],
trigger: 'onChange',
msg: '',
pattern: ''
},
{
type: 'input',
name: '邮箱',
placeholder: '请输入邮箱',
required: true,
key: 'email',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '请输入正确的邮箱',
pattern: /[\d\w]+\b@[a-zA-ZA-z0-9]+\.[a-z]+/g
},
{
type: 'input',
name: '公司',
placeholder: '请输入公司',
required: true,
key: 'company',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '职位',
placeholder: '请输入职位',
required: true,
key: 'position',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '身份证号码',
placeholder: '请输入身份证号码',
required: true,
key: 'id_number',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '请输入正确的身份证号码',
pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
},
{
type: 'input',
name: '编号',
placeholder: '请输入编号',
required: true,
key: 'number',
value: '',
enable_edit: true,
inputType: 'number',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '国籍',
placeholder: '请输入国籍',
required: true,
key: 'country',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '省份',
placeholder: '请输入省份',
required: true,
key: 'provinces',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '城市',
placeholder: '请输入城市',
required: true,
key: 'city',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '地址',
placeholder: '请输入地址',
required: true,
key: 'address',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '固话',
placeholder: '请输入固话',
required: true,
key: 'fixed_telephone',
value: '',
enable_edit: true,
inputType: 'tel',
trigger: 'onBlur',
msg: '请输入正确的固话',
pattern: ''
},
{
type: 'input',
name: '行业',
placeholder: '请输入行业',
required: true,
key: 'industry',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: 'QQ',
placeholder: '请输入QQ',
required: true,
key: 'qq',
value: '',
enable_edit: true,
inputType: 'number',
trigger: 'onBlur',
msg: ''
},
{
type: 'input',
name: '微信',
placeholder: '请输入微信',
required: true,
key: 'wechat',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '钉钉',
placeholder: '请输入钉钉',
required: true,
key: 'ding',
value: '',
enable_edit: true,
inputType: '',
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'input',
name: '微博',
placeholder: '请输入微博',
required: true,
key: 'weibo',
value: '',
enable_edit: true,
inputType: '',
msg: '',
trigger: 'onBlur',
pattern: ''
},
{
type: 'select',
name: '早餐',
key: 'breakfast',
placeholder: '请选择早餐',
value: '',
required: true,
optionList: ['有', '无'],
showPicker: false,
enable_edit: true,
trigger: 'onBlur',
msg: '',
pattern: ''
},
{
type: 'select',
name: '房型',
key: 'room_type',
placeholder: '请选择房型',
required: true,
value: '',
enable_edit: true,
inputType: '',
trigger: 'onChange',
optionList: ['单住', '合住', '不住'],
showPicker: false,
msg: '',
pattern: ''
},
{
type: 'datetime',
name: '入住时间',
key: 'check_in_time',
placeholder: '请选择入住时间',
required: true,
value: '',
enable_edit: true,
inputType: '',
trigger: 'onChange',
optionList: [],
showPicker: false,
msg: '',
pattern: ''
},
{
type: 'datetime',
name: '离店时间',
key: 'check_out_time',
placeholder: '请选择离店时间',
required: true,
value: '',
enable_edit: true,
inputType: '',
optionList: [],
showPicker: false,
trigger: 'onChange',
msg: '',
pattern: ''
}
]
export default allFormList
/**
* 文件下载
* @param {string} fileUrl 文件下载地址
* @param {string} fileName 文件名
* @returns {null}
*/
export function funDownload(fileUrl, fileName) {
// console.log(fileUrl)
const elink = document.createElement('a') // 创建一个a标签
elink.download = fileName // 设置a标签的下载属性
elink.style.display = 'none' // 将a标签设置为隐藏
elink.href = fileUrl // 把之前处理好的地址赋给a标签的href
document.body.appendChild(elink) // 将a标签添加到body中
elink.click() // 执行a标签的点击方法
// URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
document.body.removeChild(elink) // 移除a标签
}
/**
* 分割字符串,取得尾部
* @param {string} str 字符串
* @param {string} split 分割符
* @returns {string}
*/
export function splitStrLast(str, split) {
const fileNameArr = str.split(split)
const last = fileNameArr[fileNameArr.length - 1]
return last
}
import httpRequest from './axios'
export default function useWXShare() {
httpRequest
.post('https://node-server.ezijing.com/share/getsignature', {
appId: 'wxa41d0081d4889921',
url: location.href.split('#').pop()
})
.then(result => {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'wxa41d0081d4889921', // 必填,公众号的唯一标识
timestamp: result.timestamp, // 必填,生成签名的时间戳
nonceStr: result.noncestr, // 必填,生成签名的随机串
signature: result.token, // 必填,签名
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] // 必填,需要使用的JS接口列表
})
wx.ready(() => {
wx.updateAppMessageShareData({
title: '中国公路建设行业协会', // 分享标题
desc: '中国公路建设行业协会', // 分享描述
link: location.href,
imgUrl: 'https://webapp-pub.ezijing.com/highway/h5/banner-0420.png'
})
wx.updateTimelineShareData({
title: '中国公路建设行业协会', // 分享标题
link: location.href,
imgUrl: 'https://webapp-pub.ezijing.com/highway/h5/banner-0420.png'
})
})
})
}
......@@ -4,7 +4,7 @@ import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
import eslint from '@rollup/plugin-eslint'
export default defineConfig({
base: process.env.BUILD_ENV === 'prod' ? 'https://webapp-pub.ezijing.com/website/prod/center-register/' : '/',
base: process.env.BUILD_ENV === 'prod' ? 'https://webapp-pub.ezijing.com/website/prod/center-register-show-h5/' : '/',
plugins: [eslint({ include: '**/*.+(vue|js|jsx|ts|tsx)' }), createVuePlugin()],
server: {
open: true,
......@@ -15,12 +15,12 @@ export default defineConfig({
},
proxy: {
'/api/road': {
target: 'https://project-road-backend-api.ezijing.com',
// target: 'http://localhost-activity-backend.ezijing.com',
// target: 'http://localhost-activity-frontend.ezijing.com',
target: 'https://project-road-frontend-api.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/road/, '')
},
'/api': 'https://project-api.ezijing.com'
'/api': 'https://app.ezijing.com'
}
},
resolve: {
......@@ -30,23 +30,5 @@ export default defineConfig({
replacement: path.resolve(__dirname, 'src')
}
]
},
css: {
// 禁用SASS警告提醒
preprocessorOptions: { scss: { quietDeps: true, charset: false } },
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: atRule => {
if (atRule.name === 'charset') {
atRule.remove()
}
}
}
}
]
}
}
})
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论