feat(admin): add msh_single_admin project and harden ignore rules

Introduce the new Vue admin project into version control while tightening gitignore patterns to keep env files, logs, build artifacts, and test outputs out of commits.

Made-with: Cursor
This commit is contained in:
msh-agent
2026-04-15 19:31:32 +08:00
parent a840045fc1
commit ceac1c0340
713 changed files with 119926 additions and 0 deletions

View File

@@ -0,0 +1,202 @@
<template>
<div>
<el-form ref="pram" :model="pram" :rules="rules" label-width="100px" @submit.native.prevent>
<el-form-item label="管理员账号" prop="account">
<el-input v-model="pram.account" placeholder="管理员账号" />
</el-form-item>
<el-form-item label="管理员密码" prop="pwd">
<el-input v-model="pram.pwd" placeholder="管理员密码" clearable @input="handlerPwdInput" @clear="handlerPwdInput" />
</el-form-item>
<el-form-item v-if="pram.pwd" label="确认密码" prop="repwd">
<el-input v-model="pram.repwd" placeholder="确认密码" clearable />
</el-form-item>
<el-form-item label="管理员姓名" prop="realName">
<el-input v-model="pram.realName" placeholder="管理员姓名" />
</el-form-item>
<el-form-item label="管理员身份" prop="roles">
<el-select v-model="pram.roles" placeholder="身份" clearable multiple style="width: 100%">
<el-option v-for="(item, index) in roleList.list" :key="index" :label="item.roleName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input type="text" v-model="pram.phone" prefix="ios-contact-outline" placeholder="请输入手机号" size="large" />
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="pram.status" :active-value="true" :inactive-value="false" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handlerSubmit('pram')"
v-hasPermi="['admin:system:admin:update', 'admin:system:admin:save']">{{ isCreate === 0 ? '確定' : '更新'
}}</el-button>
<el-button @click="close">取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import * as roleApi from '@/api/role.js';
import * as systemAdminApi from '@/api/systemadmin.js';
import { Debounce } from '@/utils/validate';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
// name: "edit"
components: {},
props: {
isCreate: {
type: Number,
required: true,
},
editData: {
type: Object,
default: () => {
return { rules: [] };
},
},
},
data() {
const validatePhone = (rule, value, callback) => {
if (!value) {
return callback(new Error('请填写手机号'));
} else if (!/^1[3456789]\d{9}$/.test(value)) {
callback(new Error('手机号格式不正确!'));
} else {
callback();
}
};
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.pram.pwd) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
constants: this.$constants,
pram: {
account: null,
level: null,
pwd: null,
repwd: null,
realName: null,
roles: [],
status: null,
id: null,
phone: null,
},
roleList: [],
rules: {
account: [{ required: true, message: '请填管理员账号', trigger: ['blur', 'change'] }],
pwd: [{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] }],
repwd: [{ required: true, message: '确认密码密码', validator: validatePass, trigger: ['blur', 'change'] }],
realName: [{ required: true, message: '管理员姓名', trigger: ['blur', 'change'] }],
roles: [{ required: true, message: '管理员身份', trigger: ['blur', 'change'] }],
phone: [{ required: true, message: '请输入手机号', trigger: ['blur', 'change'] }],
},
};
},
mounted() {
this.initEditData();
if (checkPermi(['admin:system:role:list'])) this.handleGetRoleList();
},
methods: {
close() {
this.$emit('hideEditDialog');
},
handleGetRoleList() {
const _pram = {
page: 1,
limit: this.constants.page.limit[4],
status: 1,
};
roleApi.getRoleList(_pram).then((data) => {
this.roleList = data;
let arr = [];
data.list.forEach((item) => {
arr.push(item.id);
});
if (!arr.includes(Number.parseInt(this.pram.roles))) {
this.$set(this.pram, 'roles', []);
}
});
},
initEditData() {
if (this.isCreate !== 1) return;
const { account, realName, roles, level, status, id, phone } = this.editData;
this.pram.account = account;
this.pram.realName = realName;
const _roles = [];
if (roles.length > 0 && !roles.includes(',')) {
//如果权限id集合有长度并且是只有一个就将它Push进_roles这个数组
_roles.push(Number.parseInt(roles));
} else {
//否则就将多个id集合解构以后push进roles并且转换为整型
_roles.push(...roles.split(',').map((item) => Number.parseInt(item)));
}
this.pram.roles = _roles;
this.pram.status = status;
this.pram.id = id;
this.pram.phone = phone;
this.rules.pwd = [];
this.rules.repwd = [];
},
handlerSubmit: Debounce(function (form) {
this.$refs[form].validate((valid) => {
if (!valid) return;
if (this.isCreate === 0) {
this.handlerSave();
} else {
this.handlerEdit();
}
});
}),
handlerSave() {
systemAdminApi.adminAdd(this.pram).then((data) => {
this.$message.success('创建管理员成功');
this.$emit('hideEditDialog');
});
},
handlerEdit() {
this.pram.roles = this.pram.roles.join(',');
systemAdminApi.adminUpdate(this.pram).then((data) => {
this.$message.success('更新管理员成功');
this.$emit('hideEditDialog');
});
},
rulesSelect(selectKeys) {
this.pram.rules = selectKeys;
},
handlerPwdInput(val) {
if (!val) {
this.rules.pwd = [];
this.rules.repwd = [];
return;
}
this.rules.pwd = [
{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] },
{ min: 6, max: 20, message: '长度6-20个字符', trigger: ['blur', 'change'] },
];
this.rules.repwd = [
{
required: true,
message: '两次输入密码不一致',
validator: (rule, value, callback) => {
if (value === '') {
callback(new Error('两次输入密码不一致!'));
} else if (value !== this.pram.pwd) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
},
trigger: ['blur', 'change'],
},
];
},
},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,294 @@
<template>
<div class="divBox">
<el-card class="box-card">
<el-form inline size="small" @submit.native.prevent>
<el-form-item>
<el-select v-model="listPram.roles" placeholder="身份" clearable class="selWidth">
<el-option v-for="item in roleList.list" :key="item.id" :label="item.roleName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-select v-model="listPram.status" placeholder="状态" clearable class="selWidth">
<el-option
v-for="item in constants.roleListStatus"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-input v-model="listPram.realName" placeholder="姓名或者账号" clearable class="selWidth" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
<el-form inline @submit.native.prevent>
<el-form-item>
<el-button type="primary" @click="handlerOpenEdit(0)" v-hasPermi="['admin:system:admin:save']"
>添加管理员</el-button
>
</el-form-item>
</el-form>
<el-table :data="listData.list" size="mini" :header-cell-style="{ fontWeight: 'bold' }">
<el-table-column prop="id" label="ID" width="50" />
<el-table-column label="姓名" prop="realName" min-width="120" />
<el-table-column label="账号" prop="account" min-width="120" />
<el-table-column label="手机号" prop="lastTime" min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.phone | filterEmpty }}</span>
</template>
</el-table-column>
<el-table-column label="身份" prop="realName" min-width="230">
<template slot-scope="scope" v-if="scope.row.roleNames">
<el-tag
size="small"
type="info"
v-for="(item, index) in scope.row.roleNames.split(',')"
:key="index"
class="mr5"
>{{ item }}</el-tag
>
</template>
</el-table-column>
<el-table-column label="最后登录时间" prop="lastTime" min-width="180">
<template slot-scope="scope">
<span>{{ scope.row.lastTime | filterEmpty }}</span>
</template>
</el-table-column>
<el-table-column label="最后登录IP" prop="lastIp" min-width="150">
<template slot-scope="scope">
<span>{{ scope.row.lastIp | filterEmpty }}</span>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template slot-scope="scope">
<el-switch
v-if="checkPermi(['admin:system:admin:update:status'])"
v-model="scope.row.status"
:active-value="true"
:inactive-value="false"
active-text="开启"
inactive-text="关闭"
@change="onchangeIsShow(scope.row)"
/>
<span v-else>{{scope.row.status?'开启':'关闭'}}</span>
</template>
</el-table-column>
<el-table-column label="是否接收短信" min-width="100">
<template slot-scope="scope">
<el-switch
v-if="checkPermi(['admin:system:admin:update:sms'])"
v-model="scope.row.isSms"
:active-value="true"
:inactive-value="false"
active-text="开启"
inactive-text="关闭"
:disabled="!scope.row.phone"
@click.native="onchangeIsSms(scope.row)"
/>
<span v-else>{{scope.row.isSms?'开启':'关闭'}}</span>
</template>
</el-table-column>
<el-table-column label="删除标记" prop="status" min-width="100">
<template slot-scope="scope">
<span>{{ scope.row.isDel | filterYesOrNo }}</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="130" fixed="right">
<template slot-scope="scope">
<template v-if="scope.row.isDel">
<span>-</span>
</template>
<template v-else>
<el-button
type="text"
@click="handlerOpenEdit(1, scope.row)"
v-hasPermi="['admin:system:admin:info']"
>编辑</el-button
>
<el-button
type="text"
@click="handlerOpenDel(scope.row)"
v-hasPermi="['admin:system:admin:delete']"
>删除</el-button
>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="listPram.page"
:page-sizes="constants.page.limit"
:layout="constants.page.layout"
:total="listData.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
<el-dialog
:visible.sync="editDialogConfig.visible"
:title="editDialogConfig.isCreate === 0 ? '创建身份' : '编辑身份'"
destroy-on-close
:close-on-click-modal="false"
width="700px"
>
<edit
v-if="editDialogConfig.visible"
:is-create="editDialogConfig.isCreate"
:edit-data="editDialogConfig.editData"
@hideEditDialog="hideEditDialog"
/>
</el-dialog>
</div>
</template>
<script>
import * as systemAdminApi from '@/api/systemadmin.js';
import * as roleApi from '@/api/role.js';
import edit from './edit';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
// name: "index"
components: { edit },
data() {
return {
constants: this.$constants,
listData: { list: [] },
listPram: {
account: null,
addTime: null,
lastIp: null,
lastTime: null,
level: null,
loginCount: null,
realName: null,
roles: null,
status: null,
page: 1,
limit: this.$constants.page.limit[0],
},
roleList: [],
menuList: [],
editDialogConfig: {
visible: false,
isCreate: 0, // 0=创建1=编辑
editData: {},
},
};
},
mounted() {
this.handleGetAdminList();
this.handleGetRoleList();
},
methods: {
checkPermi,
onchangeIsShow(row) {
systemAdminApi
.updateStatusApi({ id: row.id, status: row.status })
.then(async () => {
this.$message.success('修改成功');
this.handleGetAdminList();
})
.catch(() => {
row.status = !row.status;
});
},
onchangeIsSms(row) {
// this.$confirm(`此操作将${!row.isSms ? '开启' : '关闭'}验证, 是否继续?`, "提示", {
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// type: "warning"
// }).then(async () => {
// row.isSms = !row.isSms
// }).catch(() => {
// this.$message.error('取消操作')
// })
if (!row.phone)
return this.$message({
message: '请先为管理员添加手机号!',
type: 'warning',
});
systemAdminApi
.updateIsSmsApi({ id: row.id })
.then(async () => {
this.$message.success('修改成功');
this.handleGetAdminList();
})
.catch(() => {
row.isSms = !row.isSms;
});
},
handleSearch() {
this.listPram.page = 1;
this.handleGetAdminList();
},
handleSizeChange(val) {
this.listPram.limit = val;
this.handleGetAdminList();
this.handleGetRoleList(this.listPram);
},
handleCurrentChange(val) {
this.listPram.page = val;
this.handleGetAdminList();
this.handleGetRoleList(this.listPram);
},
handleGetRoleList() {
const _pram = {
page: 1,
limit: this.constants.page.limit[4],
};
roleApi.getRoleList(_pram).then((data) => {
this.roleList = data;
});
},
handlerOpenDel(rowData) {
this.$confirm('确认删除当前数据').then(() => {
const _pram = { id: rowData.id };
systemAdminApi.adminDel(_pram).then((data) => {
this.$message.success('删除数据成功');
this.handleGetAdminList();
});
});
},
handleGetAdminList() {
systemAdminApi.adminList(this.listPram).then((data) => {
this.listData = data;
// this.handlerGetMenuList()
});
},
handlerOpenEdit(isCreate, editDate) {
this.editDialogConfig.editData = editDate;
this.editDialogConfig.isCreate = isCreate;
this.editDialogConfig.visible = true;
},
handlerGetMenuList() {
// 获取菜单全部数据后做menu翻译使用
systemAdminApi.listCategroy({ page: 1, limit: 999, type: 5 }).then((data) => {
this.menuList = data.list;
this.listData.list.forEach((item) => {
const _muneText = [];
const menuids = item.rules.split(',');
menuids.map((muid) => {
this.menuList.filter((menu) => {
if (menu.id == muid) {
_muneText.push(menu.name);
}
});
});
item.rulesView = _muneText.join(',');
this.$set(item, 'rulesViews', item.rulesView);
});
});
},
hideEditDialog() {
this.editDialogConfig.visible = false;
this.handleGetAdminList();
},
},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,210 @@
<template>
<div>
<el-form ref="pram" :model="pram" label-width="100px" @submit.native.prevent>
<el-form-item
label="角色名称"
prop="roleName"
:rules="[{ required: true, message: '请填写角色名称', trigger: ['blur', 'change'] }]"
>
<el-input v-model="pram.roleName" placeholder="身份名称" />
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="pram.status" :active-value="true" :inactive-value="false" />
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<!-- <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox> -->
<el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')"
>父子联动</el-checkbox
>
<el-tree
class="tree-border"
:data="menuOptions"
show-checkbox
ref="menu"
node-key="id"
:check-strictly="!menuCheckStrictly"
empty-text="加载中请稍候"
:props="defaultProps"
></el-tree>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="handlerSubmit('pram')"
v-hasPermi="['admin:system:role:update', 'admin:system:role:save']"
>{{ isCreate === 0 ? '確定' : '更新' }}</el-button
>
<el-button @click="close">取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import * as roleApi from '@/api/role.js';
import { Debounce } from '@/utils/validate';
export default {
name: 'roleEdit',
props: {
isCreate: {
type: Number,
required: true,
},
editData: {
type: Object,
default: null,
},
},
data() {
return {
pram: {
roleName: null,
rules: '',
status: null,
id: null,
},
menuExpand: false,
menuNodeAll: false,
menuOptions: [],
menuCheckStrictly: true,
currentNodeId: [],
defaultProps: {
children: 'childList',
label: 'name',
},
menuIds: [],
};
},
mounted() {
this.initEditData();
this.getCacheMenu();
},
methods: {
close() {
this.$emit('hideEditDialog');
},
initEditData() {
if (this.isCreate !== 1) return;
const { roleName, status, id } = this.editData;
this.pram.roleName = roleName;
this.pram.status = status;
this.pram.id = id;
const loading = this.$loading({
lock: true,
text: 'Loading',
});
roleApi.getInfo(id).then((res) => {
this.menuOptions = res.menuList;
this.checkDisabled(this.menuOptions);
loading.close();
this.getTreeId(res.menuList);
this.$nextTick(() => {
this.menuIds.forEach((i, n) => {
var node = this.$refs.menu.getNode(i);
if (node.isLeaf) {
this.$refs.menu.setChecked(node, true);
}
});
});
});
},
handlerSubmit: Debounce(function (form) {
this.$refs[form].validate((valid) => {
if (!valid) return;
let roles = this.getMenuAllCheckedKeys().toString();
this.pram.rules = roles;
if (this.isCreate === 0) {
this.handlerSave();
} else {
this.handlerEdit();
}
});
}),
handlerSave() {
roleApi.addRole(this.pram).then((data) => {
this.$message.success('创建身份成功');
this.$emit('hideEditDialog');
});
},
handlerEdit() {
roleApi.updateRole(this.pram).then((data) => {
this.$message.success('更新身份成功');
this.$emit('hideEditDialog');
});
},
rulesSelect(selectKeys) {
this.pram.rules = selectKeys;
},
// 树权限(展开/折叠)
handleCheckedTreeExpand(value, type) {
if (type == 'menu') {
let treeList = this.menuOptions;
for (let i = 0; i < treeList.length; i++) {
this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
}
}
},
// 树权限(全选/全不选)
handleCheckedTreeNodeAll(value, type) {
if (type == 'menu') {
this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
}
},
// 树权限(父子联动)
handleCheckedTreeConnect(value, type) {
if (type == 'menu') {
this.menuCheckStrictly = value ? true : false;
}
},
// 所有菜单节点数据
getMenuAllCheckedKeys() {
// 目前被选中的菜单节点
let checkedKeys = this.$refs.menu.getCheckedKeys();
// 半选中的菜单节点
let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
return checkedKeys;
},
getCacheMenu() {
if (this.isCreate !== 0) return;
const loading = this.$loading({
lock: true,
text: 'Loading',
});
roleApi.menuCacheList().then((res) => {
this.menuOptions = res;
this.checkDisabled(this.menuOptions);
loading.close();
});
},
getTreeId(datas) {
for (var i in datas) {
if (datas[i].checked) this.menuIds.push(datas[i].id);
if (datas[i].childList) {
this.getTreeId(datas[i].childList);
}
}
},
checkDisabled(data) {
//设置公共权限默认勾选且不可操作
data.forEach((item) => {
if (item.id === 280 || item.id === 294 || item.id === 344) {
item.disabled = true;
item.childList.forEach((item1) => {
item1.disabled = true;
this.$nextTick(() => {
var node = this.$refs.menu.getNode(item1.id);
if (node.isLeaf) {
this.$refs.menu.setChecked(node, true);
}
});
});
}
});
},
},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,132 @@
<template>
<div class="divBox">
<el-card class="box-card">
<el-form inline size="small" @submit.native.prevent>
<el-form-item>
<el-input v-model="listPram.roleName" placeholder="请输入角色昵称" clearable class="selWidth" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click.native="handleGetRoleList">查询</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-form inline @submit.native.prevent>
<el-form-item>
<el-button type="primary" @click="handlerOpenEdit(0)"
v-hasPermi="['admin:system:role:save', 'admin:system:menu:cache:tree']">添加角色</el-button>
</el-form-item>
</el-form>
<el-table :data="listData.list" size="mini"
:header-cell-style="{ fontWeight: 'bold', background: '#f8f8f9', color: '#515a6e', height: '40px' }">
<el-table-column label="角色编号" prop="id" width="120"></el-table-column>
<el-table-column label="角色昵称" prop="roleName" min-width="130" />
<el-table-column label="状态" prop="status">
<template slot-scope="scope">
<el-switch v-if="checkPermi(['admin:system:role:update:status'])" v-model="scope.row.status"
:active-value="true" :inactive-value="false" style="width: 40px"
@change="handleStatusChange(scope.row)"></el-switch>
<span v-else>{{ scope.row.status ? '显示' : '隐藏' }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="createTime" min-width="150" />
<el-table-column label="更新时间" prop="updateTime" min-width="150" />
<el-table-column label="操作" min-width="130" fixed="right">
<template slot-scope="scope">
<el-button size="small" type="text" @click="handlerOpenEdit(1, scope.row)"
v-hasPermi="['admin:system:role:info']">编辑</el-button>
<el-button size="small" type="text" @click="handlerOpenDel(scope.row)"
v-hasPermi="['admin:system:role:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page="listPram.page" :page-sizes="constants.page.limit" :layout="constants.page.layout"
:total="listData.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
</el-card>
<el-dialog :visible.sync="editDialogConfig.visible" :title="editDialogConfig.isCreate === 0 ? '创建身份' : '编辑身份'"
destroy-on-close :close-on-click-modal="false" width="500px">
<edit v-if="editDialogConfig.visible" :is-create="editDialogConfig.isCreate"
:edit-data="editDialogConfig.editData" @hideEditDialog="hideEditDialog" ref="editForm" />
</el-dialog>
</div>
</template>
<script>
import * as roleApi from '@/api/role.js';
import edit from './edit';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
// name: "index"
components: { edit },
data() {
return {
constants: this.$constants,
listData: { list: [] },
listPram: {
createTime: null,
updateTime: null,
level: null,
page: 1,
limit: this.$constants.page.limit[0],
roleName: null,
rules: null,
status: null,
},
menuList: [],
editDialogConfig: {
visible: false,
isCreate: 0, // 0=创建1=编辑
editData: {},
},
};
},
mounted() {
this.handleGetRoleList();
},
methods: {
checkPermi,
handlerOpenDel(rowData) {
this.$confirm('确认删除当前数据').then(() => {
roleApi.delRole(rowData).then((data) => {
this.$message.success('删除数据成功');
this.handleGetRoleList();
});
});
},
handleGetRoleList() {
roleApi.getRoleList(this.listPram).then((data) => {
this.listData = data;
});
},
handlerOpenEdit(isCreate, editDate) {
isCreate === 1 ? (this.editDialogConfig.editData = editDate) : (this.editDialogConfig.editData = {});
this.editDialogConfig.isCreate = isCreate;
this.editDialogConfig.visible = true;
},
hideEditDialog() {
this.editDialogConfig.visible = false;
this.handleGetRoleList();
},
handleSizeChange(val) {
this.listPram.limit = val;
this.handleGetRoleList(this.listPram);
},
handleCurrentChange(val) {
this.listPram.page = val;
this.handleGetRoleList(this.listPram);
},
//修改状态
handleStatusChange(row) {
roleApi.updateRoleStatus(row).then((res) => {
this.$message.success('更新状态成功');
this.handleGetRoleList();
});
},
resetQuery() {
this.listPram.roleName = '';
this.handleGetRoleList();
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,11 @@
<template>
<div>
<router-view />
</div>
</template>
<script>
export default {};
</script>
<style lang="sass" scoped></style>

View File

@@ -0,0 +1,383 @@
<template>
<div class="divBox">
<el-card class="box-card">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="queryParams.name" placeholder="请输入菜单名称" clearable size="small" />
</el-form-item>
<el-form-item label="状态" prop="menuType">
<el-select v-model="queryParams.menuType" placeholder="菜单状态" clearable size="small">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-sort" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
</el-row>
<el-table v-if="refreshTable" v-loading="listLoading" :data="menuList" row-key="id"
:default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:header-cell-style="{ fontWeight: 'bold' }">
<el-table-column prop="name" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template slot-scope="scope">
<i :class="'el-icon-' + scope.row.icon" style="font-size: 20px" />
</template>
</el-table-column>
<el-table-column prop="sort" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="isShow" label="状态" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.isShow ? '' : 'danger'">{{ scope.row.isShow ? '显示' : '隐藏' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column prop="menuType" label="类型" width="80">
<template slot-scope="scope">
<span class="type_tag one" v-if="scope.row.menuType == 'M'">目录</span>
<span class="type_tag two" v-else-if="scope.row.menuType == 'C'">菜单</span>
<span class="type_tag three" v-else type="info">按钮</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['admin:system:menu:info']">修改</el-button>
<el-button type="text" icon="el-icon-plus" @click="handleAdd(scope.row)"
v-hasPermi="['admin:system:menu:add']">新增</el-button>
<el-button type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['admin:system:menu:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改菜单对话框 -->
<el-dialog :title="title" :visible.sync="open" width="680px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<treeselect v-model="form.pid" :options="menuOptions" :normalizer="normalizer" :show-count="true"
placeholder="选择上级菜单" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="菜单类型" prop="menuType">
<el-radio-group v-model="form.menuType">
<el-radio label="M">目录</el-radio>
<el-radio label="C">菜单</el-radio>
<el-radio label="A">按钮</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item v-if="form.menuType != 'A'" label="菜单图标">
<el-form-item>
<el-input placeholder="请选择菜单图标" v-model="form.icon">
<el-button slot="append" icon="el-icon-circle-plus-outline" @click="addIcon"></el-button>
</el-input>
</el-form-item>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="form.name" placeholder="请输入菜单名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="form.sort" controls-position="right" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType !== 'A'">
<!-- v-if="form.menuType == 'C'" -->
<el-form-item prop="component">
<span slot="label">
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
组件路径
</span>
<el-input v-model="form.component" placeholder="请输入组件路径" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.menuType != 'M'">
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
<span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
权限字符
</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<!-- v-if="form.menuType != 'A'" -->
<span slot="label">
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
显示状态
</span>
<el-radio-group v-model="form.isShow">
<el-radio v-for="item in showStatus" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm" v-hasPermi="['admin:system:menu:update']"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</el-card>
</div>
</template>
<script>
import { menuListApi, menuInfo, menuUpdate, menuAdd, menuDelete } from '@/api/systemadmin';
import Treeselect from '@riophae/vue-treeselect';
import '@riophae/vue-treeselect/dist/vue-treeselect.css';
import { Debounce } from '@/utils/validate';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
name: 'Menu',
components: { Treeselect },
data() {
return {
// 遮罩层
listLoading: true,
// 显示搜索条件
showSearch: true,
// 菜单表格树数据
menuList: [],
// 菜单树选项
menuOptions: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 是否展开,默认全部折叠
isExpandAll: false,
// 重新渲染表格状态
refreshTable: true,
// 查询参数
queryParams: {
name: '',
menuType: '',
},
// 表单参数
form: {},
//请求到的menu数据
menuDataList: [],
// 表单校验
rules: {
name: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }],
},
statusOptions: [
{ value: 'M', label: '目录' },
{ value: 'C', label: '菜单' },
{ value: 'A', label: '按钮' },
],
showStatus: [
{ label: '显示', value: true },
{ label: '隐藏', value: false },
],
};
},
created() {
this.getList();
},
methods: {
checkPermi,
// 点击图标
addIcon() {
const _this = this;
_this.$modalIcon(function (icon) {
_this.form.icon = icon;
});
},
/** 查询菜单列表 */
getList(num) {
this.listLoading = true;
menuListApi(this.queryParams).then((res) => {
let obj = {},
menuList = [];
res.forEach((item) => {
obj = item;
obj.parentId = item.pid;
obj.children = [];
menuList.push(obj);
});
this.menuDataList = menuList;
this.menuList = this.handleTree(menuList, 'menuId');
this.getTreeselect();
this.listLoading = false;
});
},
/** 转换菜单数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children;
}
return {
id: node.id ? node.id : 0,
label: node.name ? node.name : '主目录',
children: node.children,
};
},
/** 查询菜单下拉树结构 */
getTreeselect() {
this.menuOptions = [];
const menu = { menuId: 0, menuName: '主类目', children: [] };
menu.children = this.handleTree(this.menuDataList, 'menuId');
this.menuOptions.push(menu);
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
menuId: '',
parentId: 0,
name: '',
icon: '',
menuType: 'M',
sort: 0,
isShow: true,
component: '',
perms: '',
};
this.resetForm('form');
},
/** 搜索按钮操作 */
handleQuery() {
this.getList(1);
},
/** 重置按钮操作 */
resetQuery() {
(this.queryParams = { name: '', menuType: '' }), this.handleQuery();
},
/** 新增按钮操作 */
handleAdd(row) {
this.reset();
if (row != null && row.id) {
this.form.pid = row.id;
} else {
this.form.pid = 0;
}
this.open = true;
this.title = '添加菜单';
},
/** 展开/折叠操作 */
toggleExpandAll() {
this.refreshTable = false;
this.isExpandAll = !this.isExpandAll;
this.$nextTick(() => {
this.refreshTable = true;
});
},
/** 修改按钮操作 */
handleUpdate(row) {
const loading = this.$loading({
lock: true,
text: 'Loading',
});
this.reset();
this.getTreeselect();
menuInfo(row.id).then((response) => {
this.form = response;
this.open = true;
this.title = '修改菜单';
loading.close();
});
},
/** 提交按钮 */
submitForm: Debounce(function () {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.id != undefined) {
menuUpdate(this.form).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList(1);
});
} else {
menuAdd(this.form).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList(1);
});
}
}
});
}),
/** 删除按钮操作 */
handleDelete(row) {
this.$modal
.confirm('是否确认删除名称为"' + row.name + '"的数据项?')
.then(function () {
return menuDelete(row.id);
})
.then(() => {
this.getList(1);
this.$modal.msgSuccess('删除成功');
})
.catch(() => { });
},
},
};
</script>
<style lang="scss">
.mb8 {
margin-bottom: 8px;
}
.type_tag {
display: inline-block;
height: 32px;
padding: 0 10px;
line-height: 30px;
font-size: 12px;
border-radius: 4px;
box-sizing: border-box;
white-space: nowrap;
}
.two {
background: rgba(239, 156, 32, 0.1);
color: rgba(239, 156, 32, 1);
}
.one {
background: rgba(75, 202, 213, 0.1);
color: rgba(75, 202, 213, 1);
}
.three {
color: rgba(120, 128, 160, 1);
background: rgba(120, 128, 160, 0.1);
}
</style>

View File

@@ -0,0 +1,213 @@
<template>
<div class="divBox">
<el-card class="box-card" :bordered="false" shadow="never">
<div v-loading="loading">
<el-tabs
tab-position="left"
v-model="agreementValue"
@tab-click="tabStatus"
v-hasPermi="[
'admin:agreement:user:info',
'admin:agreement:userprivacy:info',
'admin:agreement:useraccountcancel:info',
'admin:agreement:useraccountcancelnotice:info',
'admin:agreement:aboutus:info',
'admin:agreement:intelligent:info',
'admin:agreement:coupon:agreement:info',
]"
>
<el-tab-pane :label="item.title" v-for="(item, index) in tabList" :key="index" :name="item.info">
<div class="content">
<div class="phoneBox">
<div class="fontBox" v-html="formValidate.agreement"></div>
</div>
<div class="ueditor">
<div class="font"><span class="verticalLine"></span> {{ item.title }}</div>
<Tinymce v-model="formValidate.agreement" :key="keyIndex"></Tinymce>
</div>
</div>
</el-tab-pane>
</el-tabs>
<div class="btn">
<el-button
class="button"
type="primary"
@click="submenus"
v-hasPermi="[
'admin:agreement:user:save',
'admin:agreement:userprivacy:save',
'admin:agreement:useraccountcancel:save',
'admin:agreement:useraccountcancelnotice:save',
'admin:agreement:aboutus:save',
'admin:agreement:intelligent:save',
'admin:agreement:coupon:agreement:save',
]"
>提交</el-button
>
</div>
</div>
</el-card>
</div>
</template>
<script>
// +---------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +---------------------------------------------------------------------
// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
// +---------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +---------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +---------------------------------------------------------------------
import Tinymce from '@/components/Tinymce/index';
import { agreementInfoApi, agreementSaveApi } from '@/api/agreement';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
name: 'agreements',
components: { Tinymce },
data() {
return {
loading: false,
tabList: [
{ title: '用户协议', info: 'userinfo', save: 'usersave' },
{ title: '隐私协议', info: 'userprivacyinfo', save: 'userprivacysave' },
{ title: '关于我们', info: 'aboutusinfo', save: 'aboutussave' },
{ title: '资质证照', info: 'intelligentinfo', save: 'intelligentsave' },
{ title: '注销协议', info: 'useraccountcancelinfo', save: 'useraccountcancelsave' },
{ title: '注销声明', info: 'useraccountcancelnoticeinfo', save: 'useraccountcancelnoticesave' },
{ title: '优惠券协议', info: 'coupon/agreement/info', save: 'coupon/agreement/save' },
],
formValidate: {
agreement: '',
},
agreementValue: 'userinfo',
agreementSave: 'usersave',
keyIndex: 0,
};
},
created() {
if (
checkPermi([
'admin:agreement:user:info',
'admin:agreement:userprivacy:info',
'admin:agreement:useraccountcancel:info',
'admin:agreement:useraccountcancelnotice:info',
'admin:agreement:aboutus:info',
'admin:agreement:intelligent:info',
'admin:agreement:coupon:agreement:info',
])
)
this.getInfo(this.agreementValue);
},
methods: {
checkPermi,
getInfo(data) {
this.loading = true;
this.formValidate.agreement = '';
agreementInfoApi(data)
.then((res) => {
this.formValidate.agreement = res ? JSON.parse(res).agreement : '';
this.keyIndex += 1;
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
submenus() {
if (this.formValidate.agreement === '' || !this.formValidate.agreement) {
return this.$message.warning('请输入协议信息!');
} else {
agreementSaveApi(this.agreementSave, this.formValidate).then(async (res) => {
this.$message.success('保存成功');
});
}
},
tabStatus(e) {
this.getInfo(e.name);
this.agreementSave = this.tabList[e.index].save;
},
},
};
</script>
<style scoped lang="scss">
.box-card :v-deep.el-card__body {
padding-left: 0px;
}
:v-deep.el-tabs__item.is-active {
color: var(--prev-color-primary);
background-color: #ccc;
background: #437efd1e;
}
:v-deep.el-tabs--left .el-tabs__header.is-left {
float: left;
margin-bottom: 0;
margin-right: 20px;
height: 700px;
}
.verticalLine {
border: 2px solid var(--prev-color-primary);
margin-right: 10px;
}
.btn {
border-top: 1px solid #ccc;
margin-top: 20px;
.button {
display: block;
margin: 17px auto 0px;
}
}
.content {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
img {
max-width: 100%;
}
.phoneBox {
width: 302px;
height: 543px;
background-image: url('../../../assets/imgs/phoneBox.png');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
overflow: hidden;
margin-right: 20px;
.fontBox {
margin: 0 auto;
margin-top: 45px;
width: 255px;
height: 450px;
background: #ffffff;
border: 1px solid #e2e2e2;
padding: 10px;
overflow: hidden;
overflow-y: auto;
::v-deep img {
width: 100% !important;
}
}
}
.ueditor {
flex: 1;
.font {
font-size: 20px;
font-weight: 600;
color: #303133;
margin-bottom: 30px;
}
}
}
</style>

View File

@@ -0,0 +1,555 @@
<template>
<el-drawer
v-if="dialogVisible"
title="运费模板"
:visible.sync="dialogVisible"
size="1000px"
direction="rtl"
:before-close="handleClose"
:append-to-body="true"
:modal-append-to-body="false"
:wrapperClosable="false"
>
<div class="demo-drawer__content">
<el-form ref="ruleForm" :model="ruleForm" label-width="100px" size="mini" v-if="dialogVisible" :rules="rules">
<el-form-item label="模板名称" prop="name">
<el-input v-model="ruleForm.name" class="withs" placeholder="请输入模板名称" />
</el-form-item>
<el-form-item label="包邮方式" prop="appoint">
<el-radio-group v-model="ruleForm.appoint" @change="changeAppoint">
<el-radio :label="0">全国包邮</el-radio>
<el-radio :label="1">部分包邮</el-radio>
<el-radio :label="2">自定义</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="Number(ruleForm.appoint) > 0">
<el-form-item label="计费方式" prop="type">
<el-radio-group v-model="ruleForm.type" @change="changeRadio(ruleForm.type)">
<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="region">
<el-table
v-loading="listLoading"
:data="ruleForm.region"
border
fit
highlight-current-row
style="width: 100%"
size="mini"
class="tempBox"
>
<el-table-column align="center" label="送达到" min-width="260" prop="city_ids">
<template slot-scope="scope">
<span v-if="scope.$index === 0 && ruleForm.appoint === 2">默认运费</span>
<el-cascader
v-else
v-model="scope.row.city_ids"
style="width: 98%"
:rules="rules.city_ids"
:options="cityList"
:props="props"
collapse-tags
filterable
@change="changeRegion"
/>
</template>
</el-table-column>
<el-table-column min-width="120px" align="center" :label="columns.title" prop="first">
<template slot-scope="scope">
<el-form-item :rules="rules.first" :prop="'region.' + scope.$index + '.first'">
<el-input-number
v-model="scope.row.first"
controls-position="right"
:step-strictly="ruleForm.type === 1 ? true : false"
:min="ruleForm.type === 1 ? 1 : 0.1"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column min-width="120px" align="center" label="运费(元)" prop="firstPrice">
<template slot-scope="scope">
<el-form-item :rules="rules.firstPrice" :prop="'region.' + scope.$index + '.firstPrice'">
<el-input-number v-model="scope.row.firstPrice" controls-position="right" :min="0" />
</el-form-item>
</template>
</el-table-column>
<el-table-column min-width="120px" align="center" :label="columns.title2" prop="renewal">
<template slot-scope="scope">
<el-form-item :rules="rules.renewal" :prop="'region.' + scope.$index + '.renewal'">
<el-input-number
v-model="scope.row.renewal"
controls-position="right"
:step-strictly="ruleForm.type === 1 ? true : false"
:min="ruleForm.type === 1 ? 1 : 0.1"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
class-name="status-col"
align="center"
label="续费(元)"
min-width="120"
prop="renewalPrice"
>
<template slot-scope="scope">
<el-form-item :rules="rules.renewalPrice" :prop="'region.' + scope.$index + '.renewalPrice'">
<el-input-number v-model="scope.row.renewalPrice" controls-position="right" :min="0" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" label="操作" min-width="80">
<template slot-scope="scope">
<el-button
v-if="ruleForm.appoint === 1 || (ruleForm.appoint !== 1 && scope.$index > 0)"
type="text"
size="small"
@click="confirmEdit(ruleForm.region, scope.$index)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-edit" @click="addRegion(ruleForm.region)">
添加区域
</el-button>
</el-form-item>
<el-form-item v-if="ruleForm.appoint === 2" label="包邮区域">
<el-table
v-loading="listLoading"
:data="ruleForm.free"
border
fit
highlight-current-row
style="width: 100%"
size="mini"
>
<el-table-column align="center" label="选择区域" min-width="220">
<template slot-scope="{ row }">
<el-cascader
v-model="row.city_ids"
style="width: 95%"
:options="cityList"
:props="props"
collapse-tags
clearable
/>
</template>
</el-table-column>
<el-table-column min-width="180px" align="center" :label="columns.title3">
<template slot-scope="{ row }">
<el-input-number
v-model="row.number"
controls-position="right"
:step-strictly="ruleForm.type === 1 ? true : false"
:min="ruleForm.type === 1 ? 1 : 0.1"
/>
</template>
</el-table-column>
<el-table-column min-width="120px" align="center" label="包邮金额(元)">
<template slot-scope="{ row }">
<el-input-number v-model="row.price" controls-position="right" />
</template>
</el-table-column>
<el-table-column align="center" label="操作" min-width="120">
<template slot-scope="scope">
<el-button type="text" size="small" @click="confirmEdit(ruleForm.free, scope.$index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item v-if="ruleForm.appoint === 2">
<el-button type="primary" icon="el-icon-edit" @click="addFree(ruleForm.free)">
添加指定包邮区域
</el-button>
</el-form-item>
</template>
<el-form-item label="排序">
<el-input v-model="ruleForm.sort" class="withs" placeholder="请输入排序" />
</el-form-item>
</el-form>
</div>
<div class="demo-drawer__footer from-foot-btn btn-shadow drawer_fix">
<el-button @click="handleClose('ruleForm')"> </el-button>
<el-button
type="primary"
:loading="loading"
@click="onsubmit('ruleForm')"
v-hasPermi="['admin:shipping:templates:update']"
> </el-button
>
</div>
<span slot="footer" class="dialog-footer"> </span>
</el-drawer>
</template>
<script>
import * as logistics from '@/api/logistics';
import { Loading } from 'element-ui';
import { Debounce } from '@/utils/validate';
const defaultRole = {
name: '',
type: 1,
appoint: 0,
sort: 0,
region: [
{
first: 1,
firstPrice: 0,
renewal: 0,
renewalPrice: 0,
city_ids: [],
cityId: 0,
},
],
undelivery: 0,
free: [],
undelives: {},
};
const kg = '重量kg';
const m = '体积';
const statusMap = [
{
title: '首件',
title2: '续件',
title3: '包邮件数',
},
{
title: `首件${kg}`,
title2: `续件${kg}`,
title3: `包邮${kg}`,
},
{
title: `首件${m}`,
title2: `续件${m}`,
title3: `包邮${m}`,
},
];
export default {
name: 'CreatTemplates',
components: {},
data() {
return {
loading: false,
rules: {
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
free: [{ type: 'array', required: true, message: '请至少添加一个区域', trigger: 'change' }],
appoint: [{ required: true, message: '请选择包邮方式', trigger: 'change' }],
undelivery: [{ required: true, message: '请选择是否指定区域不配送', trigger: 'change' }],
type: [{ required: true, message: '请选择计费方式', trigger: 'change' }],
region: [{ required: true, message: '请选择区域运费', trigger: 'change' }],
city_ids: [{ type: 'array', required: true, message: '请至少选择一个区域', trigger: 'change' }],
first: [{ required: true, message: '请输入', trigger: 'blur' }],
renewal: [{ required: true, message: '请输入', trigger: 'blur' }],
firstPrice: [{ required: true, message: '请输入运费', trigger: 'blur' }],
renewalPrice: [{ required: true, message: '请输入续费', trigger: 'blur' }],
},
nodeKey: 'city_ids',
props: {
children: 'child',
label: 'name',
value: 'cityId',
multiple: true,
},
dialogVisible: false,
ruleForm: Object.assign({}, defaultRole),
listLoading: false,
cityList: [],
columns: {
title: '首件',
title2: '续件',
title3: '包邮件数',
},
tempId: 0,
regionNew: [
{
first: 1,
firstPrice: 0,
renewal: 0,
renewalPrice: 0,
city_ids: [],
cityId: 0,
},
],
type: 0, // 0添加 1编辑
};
},
mounted() {
this.listLoading = false;
let cityList = JSON.parse(sessionStorage.getItem('cityList'));
this.cityList = cityList;
},
methods: {
changeAppoint() {
this.listLoading = false;
let region = [...this.ruleForm.region];
},
changType(type) {
this.type = type;
},
confirmEdit(row, index) {
row.splice(index, 1);
},
popoverHide() {},
handleClose() {
this.dialogVisible = false;
this.ruleForm = {
name: '',
type: 1,
appoint: 0,
sort: 0,
region: [
{
first: 0,
firstPrice: 0,
renewal: 0,
renewalPrice: 0,
city_ids: [],
cityId: 0,
},
],
undelivery: 0,
free: [],
undelives: {},
};
this.columns = Object.assign({}, statusMap[0]);
},
changeRegion(value) {},
changeRadio(num) {
this.columns = Object.assign({}, statusMap[num - 1]);
},
// 添加配送区域
addRegion(region) {
region.push(
Object.assign(
{},
{
first: 0,
firstPrice: 0,
renewal: 0,
renewalPrice: 0,
city_ids: [],
cityId: '',
},
),
);
},
addFree(Free) {
Free.push(
Object.assign(
{},
{
number: 1,
price: 1,
city_ids: [],
cityId: '',
},
),
);
},
/**
* 详情
* id 模板id
* appoint true包邮 false不包邮
**/
getInfo(id, appoint) {
this.tempId = id;
const loadingInstance = Loading.service({ fullscreen: true });
logistics
.templateDetailApi({ id })
.then((res) => {
this.dialogVisible = true;
const info = res;
if (info.appoint === 0) info.type = 1;
if (Number(info.appoint) > 0) {
if (info.regionList && info.regionList.length > 0) {
info.regionList.forEach((item, index) => {
item.title = JSON.parse(item.title);
item.city_ids = item.title;
});
}
if (info.freeList && info.freeList.length > 0) {
info.freeList.forEach((item, index) => {
item.title = JSON.parse(item.title);
item.city_ids = item.title;
});
}
}
this.ruleForm = Object.assign(this.ruleForm, {
name: info.name,
type: info.type,
appoint: info.appoint,
sort: info.sort,
region: info.regionList || [], // 运费区域
free: info.freeList || [], // 包邮区域
});
this.regionNew = [...this.ruleForm.region];
this.columns = Object.assign({}, statusMap[this.ruleForm.type - 1]);
this.$nextTick(() => {
loadingInstance.close();
});
})
.catch((res) => {
// console.integralLog(res)
this.$message.error(res.message);
this.$nextTick(() => {
loadingInstance.close();
});
});
},
// 列表
getCityList() {
logistics
.cityListTree()
.then((res) => {
sessionStorage.setItem('cityList', JSON.stringify(res));
let cityList = JSON.parse(sessionStorage.getItem('cityList'));
this.cityList = cityList;
})
.catch((res) => {
this.$message.error(res.message);
});
},
change(idBox) {
idBox.map((item) => {
const ids = [];
item.city_ids.map((j) => {
j.splice(0, 1);
ids.push(j[0]);
});
item.city_ids = ids;
});
return idBox;
},
changeOne(idBox) {
const city_ids = [];
idBox.map((item) => {
item.splice(0, 1);
city_ids.push(item[0]);
});
return city_ids;
},
onsubmit: Debounce(function (formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.loading = true;
this.listLoading = true;
const param = {
appoint: this.ruleForm.appoint,
name: this.ruleForm.name,
sort: this.ruleForm.sort,
type: this.ruleForm.type,
// 配送区域及运费
shippingTemplatesRegionRequestList: [],
// 指定包邮设置
shippingTemplatesFreeRequestList: [],
};
this.ruleForm.region.forEach((el, index) => {
el.title = el.city_ids.length > 0 ? JSON.stringify(el.city_ids) : JSON.stringify([[0, 0]]);
if (el.title === '[[0,0]]') {
el.cityId = '0';
} else {
for (var i = 0; i < el.city_ids.length; i++) {
el.city_ids[i].splice(0, 2);
}
el.cityId = el.city_ids.length > 0 ? el.city_ids.join(',') : '0';
}
});
param.shippingTemplatesRegionRequestList = this.ruleForm.region;
param.shippingTemplatesRegionRequestList.forEach((el, index) => {
this.$delete(el, 'city_ids');
});
this.ruleForm.free.forEach((el, index) => {
el.title = el.city_ids.length > 0 ? JSON.stringify(el.city_ids) : JSON.stringify([[0, 0]]);
if (el.title === '[[0,0]]') {
el.cityId = '0';
} else {
for (var i = 0; i < el.city_ids.length; i++) {
el.city_ids[i].splice(0, 2);
}
el.cityId = el.city_ids.length > 0 ? el.city_ids.join(',') : '0';
}
});
param.shippingTemplatesFreeRequestList = this.ruleForm.free;
param.shippingTemplatesFreeRequestList.forEach((el, index) => {
this.$delete(el, 'city_ids');
});
if (this.ruleForm.appoint === 2) {
this.ruleForm.region.map((item, index) => {
this.ruleForm.region[0].title = '[[0,0]]';
this.ruleForm.region[0].cityId = '0';
});
}
if (this.ruleForm.appoint === 0) {
this.$delete(param, 'shippingTemplatesRegionRequestList');
this.$delete(param, 'shippingTemplatesFreeRequestList');
this.ruleForm.type = 0;
}
if (this.type === 0) {
logistics
.shippingSave(param)
.then((res) => {
this.$message.success('操作成功');
this.$emit('getList');
setTimeout(() => {
this.handleClose();
}, 800);
this.loading = false;
})
.catch(() => {
this.loading = false;
});
} else {
logistics
.shippingUpdate(param, { id: this.tempId })
.then((res) => {
this.$message.success('操作成功');
this.$emit('getList');
setTimeout(() => {
this.handleClose();
this.loading = false;
this.listLoading = false;
}, 500);
})
.catch(() => {
this.loading = false;
this.listLoading = false;
});
}
} else {
return false;
}
});
}),
clear() {
this.ruleForm.name = '';
this.ruleForm.sort = 0;
},
},
};
</script>
<style scoped lang="scss">
.withs {
width: 50%;
}
.noBox {
::v-deep .el-form-item__content {
/*margin-left: 0 !important;*/
}
}
.tempBox {
::v-deep .el-input-number--mini {
width: 100px !important;
}
}
</style>

View File

@@ -0,0 +1,154 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix">
<div class="container">
<el-form ref="form" inline :model="form">
<el-form-item label="模板名称:">
<el-input v-model="form.keywords" placeholder="请输入模板名称" class="selWidth" size="small" clearable>
<el-button slot="append" icon="el-icon-search" @click="handleSearch" />
</el-input>
</el-form-item>
</el-form>
</div>
<el-button type="primary" @click="handleSubmit()"
v-hasPermi="['admin:shipping:templates:save']">添加运费模板</el-button>
</div>
<el-table v-loading="loading" :data="tableData.list" style="width: 100%" size="mini"
:header-cell-style="{ fontWeight: 'bold' }">
<el-table-column prop="id" label="ID" min-width="60" />
<el-table-column label="模板名称" min-width="180" prop="name" />
<el-table-column min-width="100" label="计费方式" prop="type">
<template slot-scope="{ row }">
<p>{{ row.type | typeFilter }}</p>
</template>
</el-table-column>
<el-table-column min-width="100" label="包邮方式" prop="appoint">
<template slot-scope="{ row }">
<p>{{ row.appoint | statusFilter }}</p>
</template>
</el-table-column>
<el-table-column label="排序" min-width="100" prop="sort" />
<el-table-column label="添加时间" min-width="150" prop="createTime" />
<el-table-column prop="address" fixed="right" width="120" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="bindEdit(scope.row)"
v-hasPermi="['admin:shipping:templates:info']">修改</el-button>
<el-button type="text" size="small" @click="bindDelete(scope.row)"
v-hasPermi="['admin:shipping:templates:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="block-pagination">
<el-pagination :page-sizes="[20, 40, 60, 80]" :page-size="tableData.limit" :current-page="tableData.page"
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" @current-change="pageChange"
@size-change="handleSizeChange" />
</div>
</el-card>
<CreatTemplates ref="addTemplates" @getList="getList" />
</div>
</template>
<script>
import CreatTemplates from './creatTemplates';
import * as logistics from '@/api/logistics.js';
export default {
name: 'ShippingTemplates',
filters: {
statusFilter(status) {
const statusMap = {
0: '全国包邮',
1: '部分包邮',
2: '自定义',
};
return statusMap[status];
},
typeFilter(status) {
const statusMap = {
0: '无',
1: '按件数',
2: '按重量',
3: '按体积',
};
return statusMap[status];
},
},
components: { CreatTemplates },
data() {
return {
isShow: false,
dialogVisible: false,
form: {
keywords: '',
},
tableData: '',
page: 1,
limit: 20,
loading: false,
};
},
created() {
this.getDataList();
},
methods: {
// 添加
handleSubmit() {
this.$refs.addTemplates.dialogVisible = true;
if (!sessionStorage.getItem('cityList')) this.$refs.addTemplates.getCityList();
this.$refs.addTemplates.changType(0);
},
handleSearch() {
this.page = 1;
this.getDataList();
},
// 分页
pageChange(e) {
this.page = e;
this.getDataList();
},
handleSizeChange(e) {
this.limit = e;
this.getDataList();
},
// 数据列表
getDataList() {
this.loading = true;
logistics
.shippingTemplatesList({
keywords: this.form.keywords,
page: this.page,
limit: this.limit,
})
.then((res) => {
this.loading = false;
this.tableData = res;
});
},
// 编辑
bindEdit(item) {
if (!sessionStorage.getItem('cityList')) this.$refs.addTemplates.getCityList();
this.$refs.addTemplates.getInfo(item.id, item.appoint);
this.$refs.addTemplates.changType(1);
},
// 删除
bindDelete(item) {
this.$modalSure().then(() => {
logistics.shippingDetete({ id: item.id }).then((res) => {
this.$message.success('删除成功');
this.getDataList();
});
});
// logistics.shippingDetete()
},
getList() {
this.getDataList();
},
},
};
</script>
<style scoped lang="scss">
.selWidth {
width: 350px;
}
</style>

View File

@@ -0,0 +1,11 @@
<template>
<div>
<router-view />
</div>
</template>
<script>
export default {};
</script>
<style lang="sass" scoped></style>

View File

@@ -0,0 +1,298 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div class="clearfix">
<div class="container">
<el-form size="small" label-width="100px" :inline="true">
<el-form-item label="时间选择:" class="width100">
<el-radio-group
v-model="tableFrom.dateLimit"
type="button"
class="mr20"
size="small"
@change="selectChange(tableFrom.dateLimit)"
>
<el-radio-button v-for="(item, i) in fromList.fromTxt" :key="i" :label="item.val">{{
item.text
}}</el-radio-button>
</el-radio-group>
<el-date-picker
v-model="timeVal"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
size="small"
type="daterange"
placement="bottom-end"
placeholder="自定义时间"
style="width: 250px"
@change="onchangeTime"
/>
</el-form-item>
<el-form-item label="选择门店:">
<el-select
v-model="tableFrom.storeId"
filterable
placeholder="请选择"
class="selWidth"
clearable
@change="getList(1)"
>
<el-option v-for="item in storeSelectList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="关键字:">
<el-input
v-model="tableFrom.keywords"
placeholder="请输入姓名、电话、订单ID"
class="selWidth"
size="small"
clearable
>
<el-button slot="append" icon="el-icon-search" size="small" @click="getList(1)" />
</el-input>
</el-form-item>
</el-form>
</div>
</div>
</el-card>
<div class="mt20">
<cards-data :card-lists="cardLists" />
</div>
<el-card class="box-card">
<el-table
v-loading="listLoading"
:data="tableData.data"
style="width: 100%"
size="mini"
class="table"
highlight-current-row
:header-cell-style="{ fontWeight: 'bold' }"
>
<el-table-column label="订单号" prop="orderId" min-width="200" />
<el-table-column prop="realName" label="用户信息" min-width="100" />
<el-table-column label="推荐人信息" min-width="100">
<template slot-scope="scope">
<span>{{ scope.row.spreadInfo.name }}</span>
</template>
</el-table-column>
<el-table-column label="商品信息" min-width="400">
<template slot-scope="scope">
<el-popover trigger="hover" placement="right">
<div v-if="scope.row.productList && scope.row.productList.length" slot="reference">
<div
v-for="(val, i) in scope.row.productList"
:key="i"
class="tabBox acea-row row-middle"
style="flex-wrap: inherit"
>
<div class="demo-image__preview mr10">
<el-image :src="val.info.image" :preview-src-list="[val.info.image]" />
</div>
<div class="text_overflow">
<span class="tabBox_tit mr10"
>{{ val.info.productName + ' | ' }}{{ val.info.sku ? val.info.sku : '-' }}</span
>
<span class="tabBox_pice">{{
'¥' + val.info.price ? val.info.price + ' x ' + val.info.payNum : '-'
}}</span>
</div>
</div>
</div>
<div class="pup_card" v-if="scope.row.productList && scope.row.productList.length">
<div
v-for="(val, i) in scope.row.productList"
:key="i"
class="tabBox acea-row row-middle"
style="flex-wrap: inherit"
>
<div class="">
<span class="tabBox_tit mr10"
>{{ val.info.productName + ' | ' }}{{ val.info.sku ? val.info.sku : '-' }}</span
>
<span class="tabBox_pice">{{
'¥' + val.info.price ? val.info.price + ' x ' + val.info.payNum : '-'
}}</span>
</div>
</div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="payPrice" label="实际支付" min-width="100" />
<el-table-column prop="clerkName" label="核销员" min-width="100" />
<el-table-column prop="storeName" label="核销门店" min-width="150" />
<el-table-column label="支付状态" min-width="80">
<template slot-scope="scope">
<span>{{ scope.row.paid | paidFilter }}</span>
</template>
</el-table-column>
<el-table-column label="订单状态" min-width="100">
<template slot-scope="scope">
<span>{{ scope.row.statusStr.value }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="下单时间" min-width="150" />
</el-table>
<div class="block">
<el-pagination
:page-sizes="[20, 40, 60, 80]"
:page-size="tableFrom.limit"
:current-page="tableFrom.page"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.total"
@size-change="handleSizeChange"
@current-change="pageChange"
/>
</div>
</el-card>
</div>
</template>
<script>
import { orderListApi, storeListApi } from '@/api/storePoint';
import cardsData from '@/components/cards/index';
export default {
components: { cardsData },
data() {
return {
storeSelectList: [],
orderId: 0,
tableData: {
data: [],
total: 0,
},
listLoading: true,
tableFrom: {
keywords: '',
storeId: '',
dateLimit: '',
page: 1,
limit: 20,
},
timeVal: [],
fromList: this.$constants.fromList,
ids: '',
cardLists: [],
};
},
mounted() {
this.storeList();
this.getList();
},
methods: {
storeList() {
let artFrom = {
page: 1,
limit: 999,
status: '1',
keywords: '',
};
storeListApi(artFrom).then((res) => {
this.storeSelectList = res.list;
});
},
pageChangeLog(page) {
this.tableFromLog.page = page;
this.getList();
},
handleSizeChangeLog(val) {
this.tableFromLog.limit = val;
this.getList();
},
// 选择时间
selectChange(tab) {
this.tableFrom.date = tab;
this.tableFrom.page = 1;
this.timeVal = [];
this.getList();
},
// 具体日期
onchangeTime(e) {
this.timeVal = e;
this.tableFrom.dateLimit = e ? this.timeVal.join(',') : '';
this.tableFrom.page = 1;
this.getList();
},
// 列表
getList(num) {
this.listLoading = true;
this.tableFrom.page = num ? num : this.tableFrom.page;
orderListApi(this.tableFrom)
.then((res) => {
this.tableData.data = res.list.list;
this.tableData.total = res.list.total;
this.cardLists = [
{ name: '订单数量', count: res.total, color: '#1890FF', class: 'one', icon: 'icondingdan' },
{ name: '订单金额', count: res.orderTotalPrice, color: '#A277FF', class: 'two', icon: 'icondingdanjine' },
{ name: '退款总单数', count: res.refundTotal, color: '#EF9C20', class: 'three', icon: 'icondingdanguanli' },
{
name: '退款总金额',
count: res.refundTotalPrice,
color: '#1BBE6B',
class: 'four',
icon: 'iconshangpintuikuanjine',
},
];
// this.cardLists = res.data.stat
this.listLoading = false;
})
.catch(() => {
this.listLoading = false;
});
},
pageChange(page) {
this.tableFrom.page = page;
this.getList();
},
handleSizeChange(val) {
this.tableFrom.limit = val;
this.getList();
},
},
};
</script>
<style lang="scss" scoped>
.demo-table-expand {
::v-deep label {
width: 83px !important;
}
}
.selWidth {
width: 300px;
}
.el-dropdown-link {
cursor: pointer;
color: #409eff;
font-size: 12px;
}
.el-icon-arrow-down {
font-size: 12px;
}
.tabBox_tit {
width: 60%;
font-size: 12px !important;
margin: 0 2px 0 10px;
letter-spacing: 1px;
padding: 5px 0;
box-sizing: border-box;
}
.text_overflow {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pup_card {
width: 200px;
border-radius: 5px;
padding: 5px;
box-sizing: border-box;
font-size: 12px;
line-height: 16px;
}
.flex-column {
display: flex;
flex-direction: column;
}
</style>

View File

@@ -0,0 +1,177 @@
<template>
<el-dialog
v-model="dialogFormVisible"
:title="id ? '修改核销员' : '添加核销员'"
:visible.sync="dialogFormVisible"
width="750px"
@close="cancel"
>
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="150px"
class="demo-ruleForm"
@submit.native.prevent
v-loading="loading"
>
<el-form-item label="管理员:" prop="uid">
<span v-text="ruleForm.avatar"></span>
<el-button type="primary" size="small" @click="upImg">选择管理员</el-button>
</el-form-item>
<el-form-item label="所属提货点:" prop="storeId">
<el-select v-model="ruleForm.storeId" placeholder="请选择" style="width: 50%" clearable>
<el-option v-for="item in storeSelectList" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="核销员名称:">
<el-input v-model="ruleForm.staffName" placeholder="请输入核销员名称" class="dialogWidth"></el-input>
</el-form-item>
<el-form-item label="手机号码:">
<el-input v-model="ruleForm.phone" placeholder="请输入手机号码" class="dialogWidth"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="editForm('ruleForm')" v-if="id" v-hasPermi="['admin:system:staff:update']"
>修改</el-button
>
<el-button type="primary" @click="submitForm('ruleForm')" v-else v-hasPermi="['admin:system:staff:save']"
>提交</el-button
>
</div>
<customer-info ref="customer" @upImgUid="upImgUid"></customer-info>
</el-dialog>
</template>
<script>
import customerInfo from '@/components/customerInfo';
import { storeStaffSaveApi, storeStaffUpdateApi, storeStaffInfoApi, storeListApi } from '@/api/storePoint';
import { getStoreStaff } from '@/libs/public';
import { Debounce } from '@/utils/validate';
export default {
name: 'addClerk',
components: { customerInfo },
props: {
storeSelectList: Array,
},
data() {
const validateUpload = (rule, value, callback) => {
if (!this.ruleForm.avatar) {
callback(new Error('请上传商城用户图片'));
} else {
callback();
}
};
return {
loading: false,
dialogFormVisible: false,
id: 0,
ruleForm: {
phone: '',
storeId: '',
uid: '',
avatar: '',
},
name: '',
rules: {
uid: [{ required: true, message: '请选择管理员', trigger: 'change' }],
storeId: [{ required: true, message: '请选择提货点地址', trigger: 'change' }],
},
};
},
created() {},
mounted() {},
methods: {
//接收来自子集的值;
upImgUid(row) {
this.ruleForm.avatar = row.account;
this.ruleForm.uid = row.id;
},
upImg() {
this.$refs.customer.dialogFormVisible = true;
this.$refs.customer.tableList();
},
//详情
getInfo(id) {
this.id = id;
this.loading = true;
storeStaffInfoApi({ id: id })
.then((res) => {
this.ruleForm = res;
this.loading = false;
})
.catch((res) => {
this.loading = false;
});
},
//取消
cancel() {
this.dialogFormVisible = false;
this.clearFrom();
this.resetForm('ruleForm');
this.ruleForm.avatar = '';
this.id = 0;
},
//数据归为初始状态
clearFrom() {
this.ruleForm.phone = '';
this.ruleForm.staffName = '';
},
//重置
resetForm(name) {
this.$refs[name].resetFields();
},
// 提交
submitForm: Debounce(function (name) {
this.$refs[name].validate((valid) => {
if (valid) {
let phone = this.ruleForm.phone;
if (phone) {
if (!/^1[3456789]\d{9}$/.test(phone)) {
return this.$message.error('手机号格式不正确');
}
}
storeStaffSaveApi(this.ruleForm).then(async () => {
this.$message.success('提交成功');
this.dialogFormVisible = false;
this.$emit('tableList');
this.clearFrom();
this.resetForm(name);
this.id = 0;
getStoreStaff();
});
} else {
return false;
}
});
}),
// 编辑
editForm: Debounce(function (name) {
this.$refs[name].validate((valid) => {
if (valid) {
let phone = this.ruleForm.phone;
if (phone) {
if (!/^1[3456789]\d{9}$/.test(phone)) {
return this.$message.error('手机号格式不正确');
}
}
storeStaffUpdateApi(this.ruleForm).then(async () => {
this.$message.success('编辑成功');
this.dialogFormVisible = false;
this.$emit('tableList');
this.clearFrom();
this.resetForm(name);
this.id = 0;
getStoreStaff();
});
} else {
return false;
}
});
}),
},
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,147 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix">
<div class="container">
<el-form ref="form" inline :model="artFrom" size="small" @submit.native.prevent>
<el-form-item label="提货点名称:">
<el-select v-model="artFrom.storeId" placeholder="请选择" class="selWidth" clearable @change="search">
<el-option v-for="item in storeSelectList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<el-button type="primary" size="small" @click="add" v-hasPermi="['admin:system:staff:save']">添加核销员</el-button>
</div>
<el-table v-loading="loading" :data="tableData" size="small" :header-cell-style="{ fontWeight: 'bold' }">
<el-table-column prop="id" label="ID" sortable width="80"> </el-table-column>
<el-table-column prop="staffName" label="核销员名称" min-width="150"> </el-table-column>
<el-table-column prop="avatar" label="账号" min-width="150"> </el-table-column>
<el-table-column prop="phone" label="手机号码" min-width="100"> </el-table-column>
<el-table-column prop="systemStore.detailedAddress" label="所属提货点" min-width="200"> </el-table-column>
<el-table-column prop="createTime" label="添加时间" min-width="180"> </el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template slot-scope="{ row, index }">
<el-button type="text" size="small" @click="edit(row.id)"
v-hasPermi="['admin:system:staff:info']">编辑</el-button>
<!--<el-divider direction="vertical"></el-divider>-->
<el-button type="text" size="small" @click="storeDelete(row.id)"
v-hasPermi="['admin:system:staff:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="mt20" @size-change="sizeChange" @current-change="pageChange" :current-page="artFrom.page"
:page-sizes="[20, 40, 60, 100]" :page-size="artFrom.limit" layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
<add-clerk-list ref="template" @tableList="tableList" :storeSelectList="storeSelectList"></add-clerk-list>
</el-card>
</div>
</template>
<script>
import addClerkList from './addClerk';
import { storeStaffListApi, storeListApi, storeStaffDeleteApi, storeStaffUpdateStatusApi } from '@/api/storePoint';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
name: 'clerkList',
components: { addClerkList },
data() {
return {
storeSelectList: [],
artFrom: {
page: 1,
limit: 20,
storeId: '',
},
loading: false,
tableData: [],
total: 0,
};
},
created() {
if (checkPermi(['admin:system:staff:list'])) this.tableList();
this.storeList();
},
methods: {
//是否显示
onchangeIsShow(id, isShow) {
let that = this;
storeStaffUpdateStatusApi({ id: id, status: isShow })
.then(() => {
that.$message.success('操作成功');
that.tableList();
})
.catch(() => {
row.isShow = !row.isShow;
});
},
storeList() {
let artFrom = {
page: 1,
limit: 9999,
status: '1',
keywords: '',
};
storeListApi(artFrom).then((res) => {
this.storeSelectList = res.list;
});
},
tableList() {
let that = this;
that.loading = true;
storeStaffListApi(that.artFrom)
.then((res) => {
that.loading = false;
that.tableData = res.list;
that.total = res.total;
})
.catch((res) => {
that.$message.error(res.message);
});
},
//切换页数
pageChange(index) {
this.artFrom.page = index;
this.tableList();
},
//切换显示条数
sizeChange(index) {
this.artFrom.limit = index;
this.tableList();
},
//搜索
search() {
this.artFrom.page = 1;
this.tableList();
},
//刪除
storeDelete(id) {
let that = this;
that
.$modalSure()
.then(() => {
storeStaffDeleteApi({ id: id }).then(() => {
that.$message.success('删除成功');
that.tableList();
});
})
.catch((res) => {
that.$message.error(res.message);
});
},
//添加
add() {
this.$refs.template.dialogFormVisible = true;
},
//编辑
edit(id) {
this.$refs.template.dialogFormVisible = true;
this.$refs.template.getInfo(id);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,327 @@
<template>
<el-dialog
v-model="dialogFormVisible"
:title="id ? '修改提货点' : '添加提货点'"
:visible.sync="dialogFormVisible"
width="750px"
@close="cancel"
>
<template v-if="dialogFormVisible">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="150px"
class="demo-ruleForm"
@submit.native.prevent
v-loading="loading"
>
<el-form-item label="提货点名称:" prop="name">
<el-input
v-model="ruleForm.name"
maxlength="40"
placeholder="请输入提货点名称"
class="dialogWidth"
></el-input>
</el-form-item>
<el-form-item label="提货点简介:">
<el-input
v-model="ruleForm.introduction"
maxlength="100"
placeholder="请输入提货点简介"
class="dialogWidth"
></el-input>
</el-form-item>
<el-form-item label="提货点手机号:" prop="phone">
<el-input v-model="ruleForm.phone" placeholder="请输入提货点手机号" class="dialogWidth"></el-input>
</el-form-item>
<el-form-item label="提货点地址:" prop="address">
<el-cascader
class="dialogWidth"
clearable
v-model="ruleForm.address"
:options="addresData"
:props="{ value: 'name', label: 'name', children: 'child', expandTrigger: 'hover' }"
@change="handleChange"
></el-cascader>
</el-form-item>
<el-form-item label="详细地址:" prop="detailedAddress">
<el-input v-model="ruleForm.detailedAddress" placeholder="请输入详细地址" class="dialogWidth"></el-input>
</el-form-item>
<el-form-item label="提货点营业:">
<el-time-picker
is-range
v-model="dayTime"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="请选择时间营业时间"
value-format="HH:mm:ss"
@change="onchangeTime"
>
</el-time-picker>
</el-form-item>
<!-- prop="image"-->
<el-form-item label="提货点logo" :required="true">
<div class="upLoadPicBox" @click="modalPicTap('1')">
<div class="pictrue" v-if="ruleForm.image"><img :src="ruleForm.image" /></div>
<div v-else class="upLoad">
<i class="el-icon-camera cameraIconfont" />
</div>
</div>
</el-form-item>
<el-form-item label="经纬度:" prop="latitude">
<el-tooltip content="请点击查找位置选择位置">
<el-input v-model="ruleForm.latitude" placeholder="请查找位置" class="dialogWidth" readOnly>
<el-button slot="append" @click="onSearch">查找位置</el-button>
</el-input>
</el-tooltip>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="editForm('ruleForm')" v-if="id" v-hasPermi="['admin:system:store:update']"
>修改</el-button
>
<el-button type="primary" @click="submitForm('ruleForm')" v-else v-hasPermi="['admin:system:store:save']"
>提交</el-button
>
</div>
<el-dialog
v-model="modalMap"
title="上传经纬度"
:visible.sync="modalMap"
append-to-body
class="mapBox"
width="500px"
>
<iframe id="mapPage" width="100%" height="100%" frameborder="0" v-bind:src="keyUrl"></iframe>
</el-dialog>
</template>
</el-dialog>
</template>
<script>
import { storeSaveApi, storeInfoApi, storeUpdateApi } from '@/api/storePoint';
import * as logistics from '@/api/logistics';
import { configInfo } from '@/api/systemConfig';
import Templates from '../../../../appSetting/wxAccount/wxTemplate/index';
import { Debounce } from '@/utils/validate';
import { getTxMapKeyApi } from '@/api/systemConfig';
export default {
name: 'index',
components: { Templates },
// props: {
// children: 'child',
// label: 'name',
// value: 'name'
// },
data() {
const validatePhone = (rule, value, callback) => {
if (!value) {
return callback(new Error('请填写手机号'));
} else if (!/^1[3456789]\d{9}$/.test(value)) {
callback(new Error('手机号格式不正确!'));
} else {
callback();
}
};
const validateUpload = (rule, value, callback) => {
if (!this.ruleForm.image) {
callback(new Error('请上传提货点logo'));
} else {
callback();
}
};
return {
loading: false,
dialogFormVisible: false,
modalMap: false,
keyUrl: '',
addresData: [],
ruleForm: {
name: '',
introduction: '',
phone: '',
address: '',
detailedAddress: '',
dayTime: '',
image: '',
latitude: '',
},
id: 0,
dayTime: ['', ''],
rules: {
name: [{ required: true, message: '请输入提货点名称', trigger: 'blur' }],
address: [{ required: true, message: '请选择提货点地址', trigger: 'change' }],
dayTime: [{ required: true, type: 'array', message: '请选择提货点营业时间', trigger: 'change' }],
phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
detailedAddress: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
image: [{ required: true, validator: validateUpload, trigger: 'change' }],
latitude: [{ required: true, message: '请选择经纬度', trigger: 'blur' }],
},
};
},
created() {
this.ruleForm.image = '';
let cityList = JSON.parse(sessionStorage.getItem('cityList'));
this.addresData = cityList;
this.getCityList();
this.getKey();
},
mounted() {
window.addEventListener(
'message',
function (event) {
// 接收位置信息,用户选择确认位置点后选点组件会触发该事件,回传用户的位置信息
var loc = event.data;
if (loc && loc.module === 'locationPicker') {
// 防止其他应用也会向该页面post信息需判断module是否为'locationPicker'
window.parent.selectAdderss(loc);
}
},
false,
);
window.selectAdderss = this.selectAdderss;
},
methods: {
//详情
getInfo(id) {
let that = this;
that.id = id;
this.loading = true;
storeInfoApi({ id: id }).then((res) => {
that.ruleForm = res;
that.ruleForm.address = res.address.split(',');
that.dayTime = res.dayTime.split(',');
this.loading = false;
});
},
//取消
cancel() {
this.dialogFormVisible = false;
this.clearFrom();
this.ruleForm.image = '';
this.resetForm('ruleForm');
this.id = 0;
},
//重置
resetForm(name) {
this.$refs[name].resetFields();
},
// 提交
submitForm: Debounce(function (name) {
this.$refs[name].validate((valid) => {
if (valid) {
storeSaveApi(this.ruleForm).then(async () => {
this.$message.success('提交成功');
this.dialogFormVisible = false;
this.$parent.tableList();
this.$parent.storeGetCount();
this.clearFrom();
this.resetForm(name);
this.id = 0;
});
} else {
return false;
}
});
}),
//编辑
editForm: Debounce(function (name) {
this.$refs[name].validate((valid) => {
if (valid) {
this.handleChange(this.ruleForm.address);
storeUpdateApi(this.ruleForm, this.id).then(async () => {
this.$message.success('编辑成功');
this.dialogFormVisible = false;
this.$parent.tableList();
this.clearFrom();
this.resetForm(name);
this.id = 0;
});
} else {
return false;
}
});
}),
//数据归为初始状态
clearFrom() {
this.ruleForm.introduction = '';
this.dayTime = ['', ''];
},
//确认省市区
handleChange(e) {
let province = e[0];
let city = e[1];
let area = e[2];
if (e.length === 2) {
this.ruleForm.address = province + ',' + city;
} else if (e.length === 3) {
this.ruleForm.address = province + ',' + city + ',' + area;
}
},
//营业时间
onchangeTime(e) {
this.ruleForm.dayTime = e ? e.join(',') : '';
},
//上传图片
modalPicTap(tit) {
const _this = this;
this.$modalUpload(
function (img) {
_this.ruleForm.image = img[0].sattDir;
},
tit,
'system',
);
},
//查找位置
onSearch() {
this.modalMap = true;
},
// 选择经纬度
selectAdderss(data) {
this.ruleForm.latitude = data.latlng.lng + ',' + data.latlng.lat;
this.modalMap = false;
},
// key值
getKey() {
getTxMapKeyApi().then(async (res) => {
let keys = res.value;
this.keyUrl = `https://apis.map.qq.com/tools/locpicker?type=1&key=${keys}&referer=myapp`;
});
},
getCityList() {
logistics
.cityListTree()
.then((res) => {
sessionStorage.setItem('cityList', JSON.stringify(res));
let cityList = JSON.parse(sessionStorage.getItem('cityList'));
this.addresData = cityList;
})
.catch((res) => {
this.$message.error(res.message);
});
},
},
};
</script>
<style lang="scss">
.el-input-group__append,
.el-input-group__prepend {
background-color: #1890ff !important;
color: #fff !important;
border-color: #1890ff !important;
border-radius: 0 4px 4px 0;
}
.cascaderW {
width: 350px;
}
.mapBox .el-dialog__body {
height: 640px !important;
}
</style>

View File

@@ -0,0 +1,227 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-tabs
v-model="artFrom.status"
@tab-click="onClickTab"
v-if="checkPermi(['admin:system:store:count', 'admin:system:store:list'])"
>
<el-tab-pane :label="'显示中的提货点(' + headerCount.show + ')'" name="1"></el-tab-pane>
<el-tab-pane :label="'隐藏中的提货点(' + headerCount.hide + ')'" name="0"></el-tab-pane>
<el-tab-pane :label="'回收站的提货点(' + headerCount.recycle + ')'" name="2"></el-tab-pane>
</el-tabs>
<el-form ref="form" inline :model="artFrom" @submit.native.prevent>
<el-form-item label="关键字:">
<el-input
v-model="artFrom.keywords"
placeholder="请输入提货点名称/电话"
class="selWidth"
size="small"
clearable
>
<el-button slot="append" icon="el-icon-search" @click="search" />
</el-input>
</el-form-item>
</el-form>
<el-button type="primary" size="small" @click="add" v-hasPermi="['admin:system:store:save']"
>添加提货点</el-button
>
</div>
<el-table v-loading="loading" size="small" :data="tableData" :header-cell-style="{ fontWeight: 'bold' }">
<el-table-column prop="id" label="ID" min-width="80"> </el-table-column>
<el-table-column prop="image" label="提货点图片" min-width="100">
<template slot-scope="{ row, index }" class="picMiddle">
<div class="demo-image__preview">
<el-image style="width: 36px; height: 36px" :src="row.image" :preview-src-list="[row.image]" />
</div>
</template>
</el-table-column>
<el-table-column prop="name" label="提货点名称" min-width="150"> </el-table-column>
<el-table-column prop="phone" label="提货点电话" min-width="100"> </el-table-column>
<el-table-column prop="detailedAddress" label="地址" min-width="100"> </el-table-column>
<el-table-column prop="dayTime" label="营业时间" min-width="180"> </el-table-column>
<el-table-column prop="isShow" label="是否显示" min-width="100">
<template slot-scope="{ row, index }">
<el-switch
v-if="checkPermi(['admin:system:store:update:status'])"
:active-value="true"
:inactive-value="false"
active-text="显示"
inactive-text="隐藏"
v-model="row.isShow"
@change="onchangeIsShow(row.id, row.isShow)"
>
</el-switch>
<span v-else>{{row.isShow?'显示':'隐藏'}}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template slot-scope="{ row, index }">
<el-button type="text" size="small" @click="edit(row.id)" v-hasPermi="['admin:system:store:info']"
>编辑</el-button
>
<el-divider direction="vertical"></el-divider>
<el-button
v-if="artFrom.status === '2'"
type="text"
size="small"
@click="storeRecovery(row.id)"
v-hasPermi="['admin:system:store:recovery']"
>恢复</el-button
>
<el-divider v-if="artFrom.status === '2'" direction="vertical"></el-divider>
<el-button
type="text"
size="small"
@click="artFrom.status === '2' ? allDelete(row.id) : storeDelete(row.id)"
v-hasPermi="['admin:system:store:delete', 'admin:system:store:completely:delete']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
class="mt20"
@size-change="sizeChange"
@current-change="pageChange"
:current-page="artFrom.page"
:page-sizes="[20, 40, 60, 100]"
:page-size="artFrom.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</el-card>
<system-store ref="template"></system-store>
</div>
</template>
<script>
import systemStore from './addPoint';
import {
storeListApi,
storeGetCountApi,
storeUpdateStatusApi,
storeDeleteApi,
allDeleteApi,
storeRecoveryApi,
} from '@/api/storePoint';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
export default {
name: 'Point',
components: { systemStore },
data() {
return {
artFrom: {
page: 1,
limit: 20,
status: '1',
keywords: '',
},
loading: false,
tableData: [],
total: 0,
headerCount: {},
};
},
created() {
this.storeGetCount();
this.tableList();
},
methods: {
checkPermi,
//头部数量显示;
storeGetCount() {
let that = this;
storeGetCountApi().then((res) => {
that.headerCount = res;
});
},
//表格列表
tableList() {
let that = this;
that.loading = true;
storeListApi(that.artFrom).then((res) => {
that.loading = false;
that.tableData = res.list;
that.total = res.total;
});
},
//切换页数
pageChange(index) {
this.artFrom.page = index;
this.tableList();
},
//切换显示条数
sizeChange(index) {
this.artFrom.limit = index;
this.tableList();
},
//头部切换
onClickTab() {
this.artFrom.keywords = '';
this.tableList();
},
//搜索
search() {
this.artFrom.page = 1;
this.tableList();
},
//是否显示
onchangeIsShow(id, isShow) {
let that = this;
storeUpdateStatusApi({ id: id, status: isShow })
.then(() => {
that.$message.success('操作成功');
that.tableList();
that.storeGetCount();
})
.catch(() => {
row.isShow = !row.isShow;
});
},
// 恢复
storeRecovery(id) {
this.$modalSure('恢复提货吗').then(() => {
storeRecoveryApi({ id: id }).then(() => {
this.$message.success('恢复成功');
this.storeGetCount();
this.tableList();
});
});
},
//刪除
storeDelete(id) {
let that = this;
that.$modalSure('删除提货点吗?').then(() => {
storeDeleteApi({ id: id }).then(() => {
that.$message.success('删除成功');
that.storeGetCount();
that.tableList();
});
});
},
allDelete(id) {
this.$modalSure().then(() => {
allDeleteApi({ id: id }).then(() => {
this.$message.success('删除成功');
this.storeGetCount();
this.tableList();
});
});
},
//添加
add() {
this.$refs.template.dialogFormVisible = true;
},
//编辑
edit(id) {
this.$refs.template.dialogFormVisible = true;
this.$refs.template.getInfo(id);
},
},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,12 @@
<
<template>
<div>
<router-view />
</div>
</template>
<script>
export default {};
</script>
<style lang="sass" scoped></style>

View File

@@ -0,0 +1,454 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-steps :active="currentTab" align-center>
<el-step title="安装系统" />
<el-step title="应用配置" />
<el-step title="支付配置" />
<el-step title="站点配置" />
<el-step title="一号通" />
</el-steps>
</div>
<div class="install" v-show="currentTab === 0">
<div class="ins_name flex align-center">
<span>选择应用配置:</span>
<el-alert type="warning" show-icon="" title="使用前提,绑定微信平台" style="width: 300px; margin-left: 20px"
v-if="checkArr.includes(installList[0]) || checkArr.includes(installList[1])"></el-alert>
</div>
<div class="flex">
<div v-for="item in installList" :key="item.id" :class="{ active: checkArr.includes(item) }"
@click="install(item)">
<div class="ins_item">
<img :src="item.img" alt="" />
<i class="el-icon-success icon_abs" v-show="checkArr.includes(item)"></i>
</div>
<p class="ins_item_name">{{ item.name }}</p>
</div>
</div>
</div>
<div class="application" v-show="currentTab === 1">
<el-tabs v-model="applicationName" @tab-click="handleClick" v-loading="loading">
<el-tab-pane v-for="(tabItem, itemIndex) in checkArr" :key="itemIndex" :label="tabItem.name"
:name="tabItem.id.toString()">
<parser v-if="formConf.render" :is-edit="formConf.isEdit" :form-conf="formConf.content"
:form-edit-data="currentEditData" @submit="handlerSubmit" />
</el-tab-pane>
</el-tabs>
</div>
<div class="application" v-show="currentTab === 2">
<el-tabs v-model="payConfigName" @tab-click="handleClick" v-loading="loading">
<el-tab-pane v-for="(tabItem, itemIndex) in payConfigArr" :key="itemIndex" :label="tabItem.name"
:name="tabItem.extra">
<parser v-if="formConf.render" :is-edit="formConf.isEdit" :form-conf="formConf.content"
:form-edit-data="currentEditData" @submit="handlerSubmit" />
</el-tab-pane>
</el-tabs>
</div>
<div class="application" v-show="currentTab === 3">
<el-tabs v-model="siteConfigName" @tab-click="handleClick" v-loading="loading">
<el-tab-pane v-for="(tabItem, itemIndex) in siteConfigArr" :key="itemIndex" :label="tabItem.name"
:name="tabItem.extra">
<parser v-if="formConf.render" :is-edit="formConf.isEdit" :form-conf="formConf.content"
:form-edit-data="currentEditData" @submit="handlerSubmit" />
</el-tab-pane>
</el-tabs>
</div>
<div class="application flex-center" v-show="currentTab === 4">
<div class="sms_reg">
<el-form ref="formInline" :model="formInline" :rules="ruleInline" label-position="right" label-width="100px">
<div>
<p class="title mb20">一号通账户注册</p>
</div>
<el-form-item prop="phone" label="手机号码">
<el-input v-model="formInline.phone" placeholder="请输入您的手机号" style="width: 340px" />
</el-form-item>
<el-form-item prop="password" label="登录密码">
<el-input :key="passwordType" v-model="formInline.password" :type="passwordType" placeholder="密码"
tabindex="2" auto-complete="off" style="width: 340px" />
</el-form-item>
<el-form-item prop="domain" label="网址域名">
<el-input v-model="formInline.domain" placeholder="请输入网址域名" style="width: 340px" />
</el-form-item>
<el-form-item prop="code" class="captcha" label="验证码">
<div class="acea-row" style="flex-wrap: nowrap">
<el-input v-model="formInline.code" placeholder="验证码" type="text" tabindex="1"
style="width: 240px; margin-right: 10px" />
<el-button :disabled="!this.canClick" @click="cutDown" type="primary" plain
v-hasPermi="['admin:pass:send:code']">{{ cutNUm }}</el-button>
</div>
</el-form-item>
<div class="flex-center mb20">
<el-button :loading="loading" type="primary" @click="formSubmit('formInline')"
v-hasPermi="['admin:pass:register']">注册</el-button>
</div>
<div class="flex-center go_login">
<router-link to="/operation/onePass">已有帐号 去登录</router-link>
</div>
</el-form>
</div>
</div>
<el-button type="primary" class="step_btn" v-show="currentTab > 0" @click="beforeStep()">上一步</el-button>
<el-button type="primary" :class="currentTab == 0 ? 'step_btn' : ''" @click="nextStep()" v-show="currentTab < 4"
:disabled="disabled">下一步</el-button>
<el-button v-show="currentTab === 4" type="primary" @click="complate()">完成</el-button>
</el-card>
</div>
</template>
<script>
import parser from '@/components/FormGenerator/components/parser/Parser';
import * as categoryApi from '@/api/categoryApi.js';
import * as systemFormConfigApi from '@/api/systemFormConfig.js';
import * as systemSettingApi from '@/api/systemSetting.js';
import { captchaApi, registerApi } from '@/api/sms';
import { Debounce } from '@/utils/validate';
export default {
data() {
const validatePhone = (rule, value, callback) => {
if (!value) {
return callback(new Error('请填写手机号'));
} else if (!/^1[3456789]\d{9}$/.test(value)) {
callback(new Error('手机号格式不正确!'));
} else {
callback();
}
};
return {
currentTab: 0,
cTab: 0,
installList: [
{ img: require('@/assets/imgs/wechat_h5.png'), name: '公众号', id: 65 },
{ img: require('@/assets/imgs/routine.png'), name: '小程序', id: 66 },
{ img: require('@/assets/imgs/app.png'), name: 'APP', id: 134 },
],
checkArr: [],
payConfigArr: [],
siteConfigArr: [],
applicationName: '',
siteConfigName: '',
payConfigName: '',
checked: false,
formConf: { content: { fields: [] }, id: null, render: false, isEdit: false },
currentEditId: null,
currentEditData: {},
loading: false,
disabled: true,
passwordType: 'password',
cutNUm: '获取验证码',
canClick: true,
formInline: {
account: '',
code: '',
domain: '',
phone: '',
password: '',
},
ruleInline: {
password: [{ required: true, message: '请输入短信平台密码/token', trigger: 'blur' }],
domain: [{ required: true, message: '请输入网址域名', trigger: 'blur' }],
phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
},
};
},
components: { parser },
mounted() {
this.$cache.local.remove('step');
this.handlerGetTreeList();
this.getStep();
},
methods: {
install(i) {
if (this.checkArr.includes(i)) {
//includes()方法判断是否包含某一元素,返回true或false表示是否包含元素对NaN一样有效
//filter()方法用于把Array的某些元素过滤掉filter()把传入的函数依次作用于每个元素然后根据返回值是true还是false决定保留还是丢弃该元素生成新的数组
this.checkArr = this.checkArr.filter(function (ele) {
return ele != i;
});
} else {
this.checkArr.push(i);
this.applicationName = this.checkArr[0].id.toString();
if (this.checkArr.length) this.disabled = false;
}
},
nextStep() {
this.currentTab++;
switch (this.currentTab) {
case 1:
if (this.checkArr.length) {
this.handlerGetFormConfig(Number(this.applicationName));
}
break;
case 2:
this.payConfigName = this.payConfigArr[0].extra;
if (this.payConfigArr.length) {
this.handlerGetFormConfig(Number(this.payConfigName));
}
break;
case 3:
this.siteConfigName = this.siteConfigArr[0].extra;
if (this.siteConfigArr.length) {
this.handlerGetFormConfig(Number(this.siteConfigName));
}
default:
break;
}
let data = {
currentTab: this.currentTab,
checkArr: this.checkArr,
payConfigArr: this.payConfigArr,
siteConfigArr: this.siteConfigArr,
};
this.$cache.local.setJSON('step', data);
},
getStep() {
if (!this.$cache.local.has('step')) return;
let data = this.$cache.local.getJSON('step');
this.currentTab = data.currentTab ? data.currentTab : 0;
this.checkArr = data.checkArr;
this.payConfigArr = data.payConfigArr;
this.siteConfigArr = data.siteConfigArr;
if (this.checkArr.length) this.disabled = false;
if (this.currentTab == 1) {
this.applicationName = this.checkArr[0].id.toString();
this.handlerGetFormConfig(Number(this.checkArr[0].id));
} else if (this.currentTab == 2) {
this.payConfigName = this.payConfigArr[0].extra;
this.handlerGetFormConfig(Number(this.payConfigArr[0].extra));
} else if (this.currentTab == 3) {
this.siteConfigName = this.siteConfigArr[0].extra;
this.handlerGetFormConfig(Number(this.siteConfigArr[0].extra));
}
},
beforeStep() {
this.currentTab--;
this.formConf.content = { fields: [] };
this.formConf.render = false;
if (this.currentTab == 1) {
this.applicationName = this.checkArr[0].id.toString();
this.handlerGetFormConfig(Number(this.checkArr[0].id));
} else if (this.currentTab == 2) {
this.payConfigName = this.payConfigArr[0].extra;
this.handlerGetFormConfig(Number(this.payConfigArr[0].extra));
} else if (this.currentTab == 3) {
this.siteConfigName = this.siteConfigArr[0].extra;
this.handlerGetFormConfig(Number(this.siteConfigArr[0].extra));
}
},
handleClick(tab) {
let _id = tab.name ? tab.name : '';
if (!_id) return this.$message.error('表单配置不正确,请关联正确表单后使用');
this.handlerGetFormConfig(_id);
},
handlerGetFormConfig(id) {
const formPram = { id: id };
this.currentEditId = id;
this.formConf.content = { fields: [] };
this.formConf.render = false;
this.loading = true;
systemFormConfigApi
.getFormConfigInfo(formPram)
.then((data) => {
const { id, name, info, content } = data;
this.formConf.content = JSON.parse(content);
this.formConf.id = id;
this.handlerGetSettingInfo(id, 1);
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
handlerGetSettingInfo(id, level) {
systemSettingApi.systemConfigInfo({ id: id }).then((data) => {
this.currentEditData = data;
if (level === 1) {
this.formConf.isEdit = this.currentEditData !== null;
this.formConf.render = true;
}
});
},
handlerSubmit: Debounce(function (formValue) {
this.handlerSave(formValue);
}),
handlerSave(formValue) {
const _pram = this.buildFormPram(formValue);
let _formId = 0;
systemSettingApi.systemConfigSave(_pram).then((data) => {
this.$message.success('添加数据成功');
});
},
buildFormPram(formValue) {
const _pram = {
fields: [],
id: this.currentEditId,
sort: 0, // 参数暂时无用
status: true, // 参数暂时无用
};
const _fields = [];
Object.keys(formValue).forEach((key) => {
_fields.push({
name: key,
title: key,
value: formValue[key],
});
});
_pram.fields = _fields;
return _pram;
},
handlerGetTreeList() {
const _pram = { type: 6, status: 1 };
this.loading = true;
categoryApi
.treeCategroy(_pram)
.then((data) => {
this.payConfigArr = data[3].child;
this.siteConfigArr[0] = data[0].child[0];
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
formSubmit: Debounce(function (name) {
this.formInline.account = this.formInline.phone;
this.$refs[name].validate((valid) => {
if (valid) {
this.loading = true;
registerApi(this.formInline)
.then(async (res) => {
this.$message.success('注册成功');
this.loading = false;
})
.catch(() => {
this.loading = false;
});
} else {
return false;
}
});
}),
complate() {
this.$cache.local.remove('step');
this.$router.push('/');
},
cutDown() {
if (this.formInline.phone) {
if (!this.canClick) return;
this.canClick = false;
this.cutNUm = 60;
captchaApi({ phone: this.formInline.phone, types: 0 }).then(async (res) => {
this.$message.success('发送成功');
});
const time = setInterval(() => {
this.cutNUm--;
if (this.cutNUm === 0) {
this.cutNUm = '获取验证码';
this.canClick = true;
clearInterval(time);
}
}, 1000);
} else {
this.$message.warning('请填写手机号!');
}
},
},
};
</script>
<style lang="scss" scoped>
.flex {
display: flex;
}
.align-center {
align-items: center;
}
.install {
padding: 20px 0 0 105px;
.ins_name {
font-size: 14px;
color: rgba(0, 0, 0, 0.85);
font-weight: 400;
padding-bottom: 20px;
}
.ins_item {
width: 130px;
height: 130px;
background: #ffffff;
border-radius: 8px;
border: 1px solid #dddddd;
margin-right: 30px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
img {
width: 60px;
height: 60px;
}
.icon_abs {
position: absolute;
top: 6px;
right: 6px;
color: #1890ff;
font-size: 23px;
}
}
.ins_item_name {
width: 130px;
color: #333333;
font-size: 16px;
font-weight: 600;
text-align: center;
margin-top: 15px;
}
.active {
.ins_item {
border: 1px solid #1890ff;
}
.ins_item_name {
color: #1890ff;
}
}
.next_step {
margin: 54px 0 100px;
}
}
.step_btn {
margin: 54px 0 0 105px;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.sms_reg {
width: 550px;
height: 380px;
}
.title {
font-size: 16px;
text-align: center;
font-weight: 600;
color: #333333;
}
.go_login {
font-size: 12px;
font-weight: 400;
color: #1890ff;
}
</style>

View File

@@ -0,0 +1,205 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix" v-if="parentId > 0">
<el-form inline size="small">
<el-form-item>
<el-button type="primary" @click="back()">返回</el-button>
<!-- <el-button type="primary" @click="addcity()"><i class="el-icon-plus" />添加城市</el-button>-->
</el-form-item>
</el-form>
</div>
<el-table v-loading="loading" :data="tableData" size="mini" class="table" highlight-current-row>
<el-table-column prop="cityId" label="编号" min-width="100" />
<el-table-column label="上级名称" min-width="100">
<div>{{ parentName }}</div>
</el-table-column>
<el-table-column min-width="250" label="地区名称">
<template slot-scope="scope">
<el-link :underline="false" @click="cityDetail(scope.row)">{{ scope.row.name }}</el-link>
</template>
</el-table-column>
<!--<el-table-column-->
<!--label="状态"-->
<!--min-width="100"-->
<!--&gt;-->
<!--<template slot-scope="scope">-->
<!--<el-switch-->
<!--v-model="scope.row.isShow"-->
<!--class="demo"-->
<!--active-text="开启"-->
<!--inactive-text="关闭"-->
<!--@change="cityStatus(scope.row)"-->
<!--/>-->
<!--</template>-->
<!--</el-table-column>-->
<el-table-column fixed="right" min-width="80" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="editCity(scope.row)">编辑</el-button>
<!-- <el-button type="text" size="small">删除</el-button>-->
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<parser
v-if="formShow"
:form-conf="formConf"
:form-edit-data="formData"
:is-edit="isCreate === 1"
@submit="submit"
/>
</el-dialog>
</div>
</template>
<script>
import parser from '@/components/FormGenerator/components/parser/Parser';
import * as systemFormConfigApi from '@/api/systemFormConfig.js';
import * as logistics from '@/api/logistics.js';
export default {
name: 'CityList',
components: { parser },
data() {
return {
// 表单
formConf: { fields: [] },
// 生成表单id
formId: 70,
tableData: [],
// 上级名称
parentName: '中国',
// 父级城市id
parentId: 0,
loading: false,
dialogVisible: false,
// 选中id
editId: 0,
formShow: false,
formData: {},
isCreate: 0,
};
},
created() {
this.getCityList();
},
methods: {
// 获取城市数据
getCityList() {
this.loading = true;
logistics
.cityList({
parentId: this.parentId,
})
.then((data) => {
this.loading = false;
this.tableData = data;
});
},
// 城市详情
cityDetail(item) {
this.parentId = item.cityId;
this.parentName = item.name;
this.getCityList();
},
// 返回
back() {
this.parentName = '中国';
this.parentId = 0;
this.getCityList();
},
// 状态
cityStatus(e) {
logistics
.updateStatus({
id: e.id,
cityId: e.cityId,
status: e.isShow,
})
.then((res) => {
this.$message.success('操作成功');
})
.catch(() => {
e.isShow = !e.isShow;
});
},
// 编辑
editCity(item) {
this.editId = item.id;
const _pram = { id: this.formId };
systemFormConfigApi.getFormConfigInfo(_pram).then((data) => {
this.formShow = false;
this.isCreate = 0;
this.getCityInfo();
this.dialogVisible = true;
this.formConf = JSON.parse(data.content);
});
},
// 详情
getCityInfo() {
logistics
.cityInfo({
id: this.editId,
})
.then((res) => {
this.isCreate = 1;
this.formData = res;
this.formData.parentName = this.parentName;
setTimeout(() => {
// 让表单重复渲染待编辑数据
this.formShow = true;
}, 80);
});
},
submit(data) {
const param = {
id: this.editId,
parentId: this.parentId,
name: data.name,
};
logistics.cityUpdate(param).then((res) => {
this.dialogVisible = false;
this.getCityList();
});
},
// 关闭模态框
handleClose(done) {
this.formConf.fields = [];
this.dialogVisible = false;
},
},
};
</script>
<style lang="scss" scoped>
.el-icon-plus {
margin-right: 5px;
}
.demo .el-switch__label {
position: absolute;
display: none;
color: #fff;
}
/*打开时文字位置设置*/
.demo .el-switch__label--right {
z-index: 1;
}
/*关闭时文字位置设置*/
.demo .el-switch__label--left {
z-index: 1;
left: 19px;
}
/*显示文字*/
.demo .el-switch__label.is-active {
display: block;
}
.demo.el-switch .el-switch__core,
.el-switch .el-switch__label {
width: 60px !important;
}
</style>

View File

@@ -0,0 +1,265 @@
<template>
<div class="divBox">
<el-card class="box-card">
<div slot="header" class="clearfix">
<div class="container">
<el-form ref="form" inline :model="form">
<el-form-item label="关键字:">
<el-input v-model="form.keywords" placeholder="请输入关键字" class="selWidth" size="small" clearable>
<el-button slot="append" size="small" icon="el-icon-search" @click="handlerSearch" />
</el-input>
</el-form-item>
</el-form>
</div>
<el-button type="primary" size="small" @click="addExpress">同步物流公司</el-button>
</div>
<el-table v-loading="loading" :data="tableData.list" style="width: 100%">
<el-table-column prop="id" label="ID" min-width="180" />
<el-table-column label="物流公司名称" min-width="150" prop="name" />
<el-table-column min-width="200" label="编码" prop="code" />
<el-table-column min-width="100" label="排序" prop="sort" sortable />
<el-table-column label="是否显示" min-width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isShow"
class="demo"
:active-value="true"
:inactive-value="false"
active-text="开启"
inactive-text="关闭"
@change="bindStatus(scope.row)"
/>
</template>
</el-table-column>
<el-table-column prop="address" fixed="right" min-width="120" label="操作">
<template slot-scope="scope">
<el-button v-if="scope.row.net" type="text" size="small" @click="bindEdit(scope.row)"
>收件网点名称编辑</el-button
>
<el-button v-else-if="scope.row.partnerId" type="text" size="small" @click="bindEdit(scope.row)"
>月结账号编辑</el-button
>
<el-button v-else type="text" size="small" @click="bindEdit(scope.row)">编辑</el-button>
<!--<el-button type="text" size="small" @click="bindDelete(scope.row)">删除</el-button>-->
</template>
</el-table-column> </el-table
>`
<div class="block-pagination">
<el-pagination
:page-sizes="[20, 40, 60, 80]"
:page-size="tableData.limit"
:current-page="tableData.page"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.total"
@current-change="pageChange"
@size-change="handleSizeChange"
/>
</div>
</el-card>
<el-dialog title="编辑物流公司" :visible.sync="dialogVisible" width="700px" :before-close="handleClose">
<el-form :model="formData" :rules="rules" ref="formData" label-width="100px" class="demo-ruleForm">
<el-form-item label="月结账号" prop="account" v-if="formData.partnerId">
<el-input v-model="formData.account" placeholder="请输入月结账号"></el-input>
</el-form-item>
<el-form-item label="月结密码" prop="password" v-if="formData.partnerKey">
<el-input v-model="formData.password" placeholder="请输入月结密码"></el-input>
</el-form-item>
<el-form-item label="网点名称" prop="netName" v-if="formData.net">
<el-input v-model="formData.netName" placeholder="请输入网点名称"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" :max="9999" label="排序"></el-input-number>
</el-form-item>
<el-form-item label="是否启用" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="false">关闭</el-radio>
<el-radio :label="true">开启</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submit('formData')">确 定</el-button>
</span>
<!--<parser v-if="formShow" ref="formBox" class="formBox" :form-conf="formConf" :form-edit-data="formData" :is-edit="isCreate === 1" @submit="submit" />-->
</el-dialog>
</div>
</template>
<script>
import parser from '@/components/FormGenerator/components/parser/Parser';
import * as systemFormConfigApi from '@/api/systemFormConfig.js';
import * as logistics from '@/api/logistics.js';
export default {
name: 'CompanyList',
components: { parser },
data() {
return {
constants: this.$constants,
// 表单
formConf: { fields: [] },
form: {
keywords: '',
},
tableData: {},
page: 1,
limit: 20,
loading: false,
dialogVisible: false,
fromType: 'add',
formData: {
status: false,
},
isCreate: 0,
formShow: false,
editId: 0,
rules: {
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }],
account: [{ required: true, message: '请输入月结账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入月结密码', trigger: 'blur' }],
netName: [{ required: true, message: '请输入网点名称', trigger: 'blur' }],
},
};
},
created() {
this.getExpressList();
},
methods: {
handlerSearch() {
this.page = 1;
this.getExpressList();
},
// 获取物流公司列表
getExpressList() {
this.loading = true;
logistics
.expressList({
page: this.page,
limit: this.limit,
keywords: this.form.keywords,
})
.then((res) => {
this.loading = false;
this.tableData = res;
})
.catch(() => {
this.loading = false;
});
},
// 物流开关
bindStatus(item) {
logistics
.expressUpdateShow({
account: item.account,
code: item.code,
id: item.id,
isShow: item.isShow,
name: item.name,
sort: item.sort,
})
.then((res) => {
this.$message.success('操作成功');
this.getExpressList();
})
.catch(() => {
item.isShow = !item.isShow;
});
},
// 分页
pageChange(e) {
this.page = e;
this.getExpressList();
},
handleSizeChange(e) {
this.limit = e;
this.getExpressList();
},
// 添加物流公司
addExpress() {
logistics.expressSyncApi().then((data) => {
this.page = 1;
this.getExpressList();
});
},
// 删除物流公司
bindDelete(item) {
this.$modalSure().then(() => {
logistics.expressDelete({ id: item.id }).then((res) => {
this.$message.success('删除成功');
this.getExpressList();
});
});
},
// 表单提交
submit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
logistics.expressUpdate(this.formData).then((res) => {
this.$message.success('操作成功');
this.handleClose();
this.getExpressList();
});
} else {
return false;
}
});
},
// 关闭模态框
handleClose(done) {
this.formShow = false;
// this.formData = {}
this.formConf.fields = [];
this.dialogVisible = false;
this.isCreate = 0;
},
// 编辑
bindEdit(item) {
this.dialogVisible = true;
this.editId = item.id;
logistics.expressInfo({ id: item.id }).then((res) => {
this.formData = res;
});
},
},
};
</script>
<style lang="scss" scoped>
.selWidth {
width: 350px;
}
.el-icon-plus {
margin-right: 5px;
}
.demo .el-switch__label {
position: absolute;
display: none;
color: #fff;
}
/*打开时文字位置设置*/
.demo .el-switch__label--right {
z-index: 1;
}
/*关闭时文字位置设置*/
.demo .el-switch__label--left {
z-index: 1;
left: 19px;
}
/*显示文字*/
.demo .el-switch__label.is-active {
display: block;
}
.demo.el-switch .el-switch__core,
.el-switch .el-switch__label {
width: 60px !important;
}
.formBox {
.el-input-number--medium {
width: 100px;
}
}
</style>

View File

@@ -0,0 +1,11 @@
<template>
<div>
<router-view />
</div>
</template>
<script>
export default {};
</script>
<style scoped></style>

View File

@@ -0,0 +1,315 @@
<template>
<div class="divBox">
<div>
<el-card :bordered="false" class="box-card">
<div>
<el-tabs v-model="currentTab" @tab-click="changeTab">
<el-tab-pane
:label="item.label"
:name="item.value.toString()"
v-for="(item, index) in headerList"
:key="index + '-only'"
/>
</el-tabs>
</div>
<el-row type="flex" class="mb20 mt-1">
<el-col>
<el-button
type="primary"
icon="el-icon-document"
@click="syncRoutine()"
v-hasPermi="['admin:wechat:routine:sync']"
>同步小程序订阅消息</el-button
>
<el-button
type="primary"
icon="el-icon-document"
@click="syncWechat()"
v-hasPermi="['admin:wechat:whcbqhn:sync']"
>同步微信模版消息</el-button
>
</el-col>
</el-row>
<div class="description">
<p><span class="iconfont iconxiaochengxu"></span> 小程序经营类目生活服务 > 百货/超市/便利店</p>
<p>
<span class="iconfont icongongzhonghao"></span> 公众号经营类目IT科技/互联网|电子商务IT科技/IT软件与服务
</p>
</div>
<el-table
:data="levelLists"
ref="table"
class="mt25"
size="small"
v-loading="loadingList"
:header-cell-style="{ fontWeight: 'bold' }"
>
<el-table-column label="ID" prop="id" width="80"></el-table-column>
<el-table-column label="通知类型" prop="type"></el-table-column>
<el-table-column label="通知场景说明" prop="description"></el-table-column>
<el-table-column label="标识" prop="mark"></el-table-column>
<el-table-column label="公众号模板" prop="isWechat" v-if="currentTab == '1'">
<template slot-scope="scope">
<el-switch
v-if="scope.row.isWechat !== 0"
v-model="scope.row.isWechat"
:active-value="1"
:inactive-value="2"
active-text="启用"
inactive-text="禁用"
@change="changeWechat(scope.row)"
>
</el-switch>
<span v-else>{{scope.row.isWechat?'启用':'禁用'}}</span>
</template>
</el-table-column>
<el-table-column label="小程序订阅" prop="isRoutine" v-if="currentTab == '1'">
<template slot-scope="scope">
<el-switch
v-if="scope.row.isRoutine !== 0"
v-model="scope.row.isRoutine"
:active-value="1"
:inactive-value="2"
active-text="启用"
inactive-text="禁用"
@change="changeRoutine(scope.row)"
>
</el-switch>
<span v-else>{{scope.row.isRoutine?'启用':'禁用'}}</span>
</template>
</el-table-column>
<el-table-column label="发送短信" prop="isSms">
<template slot-scope="scope">
<el-switch
v-if="scope.row.isSms !== 0"
v-model="scope.row.isSms"
:active-value="1"
:inactive-value="2"
active-text="启用"
inactive-text="禁用"
@change="changeSms(scope.row)"
>
</el-switch>
<span v-else>{{scope.row.isSms?'启用':'禁用'}}</span>
</template>
</el-table-column>
<el-table-column label="设置" prop="id">
<template slot-scope="scope">
<el-button type="text" @click="setting(scope.row)" v-hasPermi="['admin:system:notification:detail']"
>详情</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<el-dialog title="通知详情" :visible.sync="centerDialogVisible" width="50%">
<el-tabs v-model="infoTab" @tab-click="changeInfo">
<el-tab-pane
:label="item.label"
:name="item.value.toString()"
v-for="(item, index) in currentTab == '1' ? infoList : infoList1"
:key="index"
/>
<el-form ref="form" :model="form" label-width="80px" v-loading="loading">
<el-form-item label="ID">
<el-input v-model="form.id" disabled></el-input>
</el-form-item>
<el-form-item label="模板名" v-if="form.name">
<el-input v-model="form.name" disabled></el-input>
</el-form-item>
<el-form-item label="模板ID" v-if="form.tempId">
<el-input v-model="form.tempId"></el-input>
</el-form-item>
<el-form-item label="模板编号" v-if="form.tempKey">
<el-input v-model="form.tempKey" disabled></el-input>
</el-form-item>
<el-form-item label="模板说明" v-if="form.title">
<el-input v-model="form.title" disabled></el-input>
</el-form-item>
<el-form-item label="模板内容" v-if="form.content">
<el-input v-model="form.content" disabled></el-input>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio label="1">开启</el-radio>
<el-radio label="2">关闭</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</el-tabs>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible = false"> </el-button>
<el-button type="primary" @click="submit()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import {
notificationListApi,
notificationRoutine,
notificationWechat,
notificationSms,
notificationDetail,
notificationUpdate,
} from '@/api/systemFormConfig';
import { wechatAsyncApi, routineAsyncApi } from '@/api/wxApi';
import { Debounce } from '@/utils/validate';
export default {
data() {
return {
modalTitle: '',
notificationModal: false,
headerList: [
{ label: '通知会员', value: '1' },
{ label: '通知平台', value: '2' },
],
id: 0,
levelLists: [],
currentTab: '1',
loading: false,
formData: {},
industry: null,
loadingList: false,
centerDialogVisible: false,
infoList: [],
infoList1: [{ label: '短信', value: 'sms' }],
form: {
content: '',
name: '',
id: '',
status: null,
tempId: '',
tempKey: '',
title: '',
},
detailType: '',
infoTab: '',
};
},
created() {
this.getNotificationList(Number(this.currentTab));
},
methods: {
changeTab(data) {
this.currentTab = data.name;
this.getNotificationList(data.name);
},
//获取消息列表
getNotificationList(id) {
this.loadingList = true;
notificationListApi({ sendType: id })
.then((res) => {
this.loadingList = false;
this.levelLists = res;
})
.catch((res) => {
this.loadingList = false;
});
},
//公众号消息开关
changeWechat(row) {
notificationWechat(row.id).then((res) => {
this.$modal.msgSuccess('修改成功');
});
},
//小程序消息开关
changeRoutine(row) {
notificationRoutine(row.id).then((res) => {
this.$modal.msgSuccess('修改成功');
});
},
//短信消息开关
changeSms(row) {
notificationSms(row.id).then((res) => {
this.$modal.msgSuccess('修改成功');
});
},
//详情tab切换
changeInfo(data) {
this.getNotificationDetail(data);
},
//详情数据
getNotificationDetail(param) {
this.loading = true;
let data = {
id: this.id,
type: param.name,
};
this.$set(this, 'detailType', data.type);
notificationDetail(data)
.then((res) => {
this.form = res;
this.$set(this.form, 'status', res.status.toString());
this.loading = false;
})
.catch((res) => {
this.loading = false;
});
},
// 设置
setting(row) {
this.infoList = [];
this.id = row.id;
this.centerDialogVisible = true;
if (row.isWechat !== 0) {
this.infoList.push({ label: '公众号模板消息', value: 'wechat' });
}
if (row.isRoutine !== 0) {
this.infoList.push({ label: '小程序订阅消息', value: 'routine' });
}
if (row.isSms !== 0) {
this.infoList.push({ label: '短信', value: 'sms' });
}
this.infoTab = this.infoList[0].value;
this.getNotificationDetail({ name: this.infoTab });
},
//修改通知
submit: Debounce(function () {
let data = {
id: this.id,
status: Number(this.form.status),
tempId: this.form.tempId,
type: this.detailType,
};
notificationUpdate(data).then((res) => {
this.$modal.msgSuccess('修改成功');
this.centerDialogVisible = false;
this.getNotificationList(this.currentTab);
});
}),
syncWechat() {
wechatAsyncApi().then((res) => {
this.$message.success('同步成功');
});
},
syncRoutine() {
routineAsyncApi().then((res) => {
this.$message.success('同步成功');
});
},
},
};
</script>
<style scoped>
.mt-1 {
margin-top: 6px;
}
.description {
padding: 16px;
position: relative;
border-radius: 4px;
margin-bottom: 20px;
color: #515a6e;
line-height: 1.5;
font-size: 14px;
border: 1px solid #abdcff;
background-color: #f0faff;
}
.iconfont {
color: #06c05f;
}
</style>

View File

@@ -0,0 +1,215 @@
<template>
<div class="divBox">
<el-card class="box-card">
<el-tabs
v-model="activeNamel1"
@tab-click="handleTabClick"
v-loading="loading"
v-if="checkPermi(['admin:system:config:info'])"
>
<el-tab-pane v-for="(tab, index) in treeList" :key="index" :label="tab.name" :name="tab.id.toString()">
<template>
<el-tabs
v-if="tab.child && tab.child.length > 0"
v-model="activeNamel2"
type="border-card"
@tab-click="handleItemTabClick"
>
<el-tab-pane
v-for="(tabItem, itemIndex) in tab.child"
:key="itemIndex"
:label="tabItem.name"
:name="tabItem.extra"
>
<parser
v-if="formConfChild.render"
:is-edit="formConfChild.isEdit"
:form-conf="formConfChild.content"
:form-edit-data="currentEditData"
@submit="handlerSubmit"
/>
</el-tab-pane>
</el-tabs>
<span v-else>
<parser
v-if="formConf.render"
:is-edit="formConf.isEdit"
:form-conf="formConf.content"
:form-edit-data="currentEditData"
@submit="handlerSubmit"
/>
</span>
</template>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</template>
<script>
import parser from '@/components/FormGenerator/components/parser/Parser';
import * as categoryApi from '@/api/categoryApi.js';
import * as selfUtil from '@/utils/ZBKJIutil.js';
import * as systemFormConfigApi from '@/api/systemFormConfig.js';
import * as systemSettingApi from '@/api/systemSetting.js';
import * as systemConfigApi from '@/api/systemConfig.js';
import Template from '@/views/appSetting/wxAccount/wxTemplate/index';
import { beautifierConf } from '@/components/FormGenerator/utils';
import { checkPermi } from '@/utils/permission'; // 权限判断函数
import { Debounce } from '@/utils/validate';
export default {
// name: "index",
components: { Template, parser },
data() {
return {
loading: false,
formConf: { content: { fields: [] }, id: null, render: false, isEdit: false },
formConfChild: { content: { fields: [] }, id: null, render: false, isEdit: false },
activeNamel1: null,
activeNamel2: '', //针对文件特殊处理
treeList: [],
editDataChild: {},
isCreate: 0,
currentEditId: null,
currentEditData: null,
currentSelectedUploadFlag: null,
};
},
mounted() {
this.handlerGetTreeList();
this.getCurrentUploadSelectedFlag();
},
methods: {
checkPermi,
handleTabClick(tab) {
this.activeNamel2 = tab.$children[0].panes[0].name;
this.handlerGetLevel2FormConfig(this.activeNamel2);
},
handlerGetLevel1FormConfig(id) {
const formPram = { id: id };
this.currentEditId = id;
this.formConf.content = { fields: [] };
this.formConf.render = false;
this.loading = true;
systemFormConfigApi
.getFormConfigInfo(formPram)
.then((data) => {
const { id, name, info, content } = data;
this.formConf.content = JSON.parse(content);
this.formConf.id = id;
this.handlerGetSettingInfo(id, 1);
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
handleItemTabClick(tab, event) {
//这里对tabs=tab.name和radio=id做了兼容
let _id = tab.name ? tab.name : tab;
if (!_id) return this.$message.error('表单配置不正确,请关联正确表单后使用');
this.handlerGetLevel2FormConfig(_id);
},
handlerGetLevel2FormConfig(id) {
const formPram = { id: id };
this.currentEditId = id;
this.formConfChild.content = { fields: [] };
this.formConfChild.render = false;
this.loading = true;
systemFormConfigApi
.getFormConfigInfo(formPram)
.then((data) => {
const { id, name, info, content } = data;
this.formConfChild.content = JSON.parse(content);
this.formConfChild.id = id;
this.handlerGetSettingInfo(id, 2);
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
// 表单详情
handlerGetSettingInfo(id, level) {
systemSettingApi.systemConfigInfo({ id: id }).then((data) => {
// 小程序登录配置,此处返回字符串,表单组件是数组,需要字符串转为数组
if (data.routine_phone_verification)
data.routine_phone_verification = data.routine_phone_verification.split(',').map(Number);
this.currentEditData = data;
if (level === 1) {
this.formConf.isEdit = this.currentEditData !== null;
this.formConf.render = true;
} else {
this.formConfChild.isEdit = this.currentEditData !== null;
this.formConfChild.render = true;
}
});
},
handlerSubmit: Debounce(function (formValue) {
this.handlerSave(formValue);
}),
handlerSave(formValue) {
const _pram = this.buildFormPram(formValue);
let _formId = 0;
systemSettingApi.systemConfigSave(_pram).then((data) => {
this.$message.success('添加数据成功');
});
},
handlerGetTreeList() {
const _pram = { type: this.$constants.categoryType[5].value, status: 1 };
this.loading = true;
categoryApi
.treeCategroy(_pram)
.then((data) => {
this.treeList = this.handleAddArrt(data);
if (this.treeList.length > 0) this.activeNamel1 = this.treeList[0].id.toString();
if (this.treeList.length > 0 && this.treeList[0].child.length > 0) {
this.activeNamel2 = this.treeList[0].child[0].extra;
}
if (this.activeNamel2) {
this.handlerGetLevel2FormConfig(this.treeList[0].child[0].extra);
}
// else {
// this.handlerGetLevel1FormConfig(this.treeList[0].extra)
//}
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
handleAddArrt(treeData) {
// let _result = this.addTreeListLabel(treeData)
const _result = selfUtil.addTreeListLabel(treeData);
return _result;
},
buildFormPram(formValue) {
const _pram = {
fields: [],
id: this.currentEditId,
sort: 0, // 参数暂时无用
status: true, // 参数暂时无用
};
const _fields = [];
Object.keys(formValue).forEach((key) => {
_fields.push({
name: key,
title: key,
// 提交数据要求是字符串,如果是数组,转为字符串
value: formValue[key] instanceof Array ? formValue[key].join(',') : formValue[key],
});
});
_pram.fields = _fields;
return _pram;
},
//获取文件存储类型
getCurrentUploadSelectedFlag() {
systemConfigApi.getUploadTypeApi().then((data) => {
this.currentSelectedUploadFlag = parseInt(data);
});
},
},
};
</script>
<style scoped></style>