系统配置
This commit is contained in:
parent
9cf598aa9c
commit
6bd45e533e
|
@ -9,6 +9,14 @@ export function listArticle(query) {
|
|||
})
|
||||
}
|
||||
|
||||
// 查询文章列表ByIds
|
||||
export function listArticleByIds(ids) {
|
||||
return request({
|
||||
url: `/system/article/listByIds/${ids}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询文章详细
|
||||
export function getArticle(articleId) {
|
||||
return request({
|
||||
|
|
|
@ -60,10 +60,11 @@ export function refreshCache() {
|
|||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKeys(configKeys) {
|
||||
export function getConfigKeys(data) {
|
||||
return request({
|
||||
url: '/system/config/configKeys/' + configKeys,
|
||||
method: 'get'
|
||||
url: '/system/config/configKeys',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
|
209
src/components/Business/Article/ArticleDialog.vue
Normal file
209
src/components/Business/Article/ArticleDialog.vue
Normal file
|
@ -0,0 +1,209 @@
|
|||
<!--version: 3, 文章选择弹窗-->
|
||||
<!--版本更新内容:添加prop属性,修复多选-->
|
||||
|
||||
<template>
|
||||
<el-dialog :title="title" :visible="show" width="60%" top="2vh" @open="open" @close="close"
|
||||
:append-to-body="true">
|
||||
<el-form size="small" :inline="true" label-width="5em" @submit.native.prevent="onSearch">
|
||||
<el-form-item label="文章标题">
|
||||
<el-input v-model="searchForm.title" clearable placeholder="请输入文章标题"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSearch()" icon="el-icon-search">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
v-loading="loadTable"
|
||||
@row-click="changeSelection"
|
||||
@row-dblclick="select"
|
||||
@select-all="selectionAll"
|
||||
@select="changeSelection"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" type="selection" v-if="multiple"></el-table-column>
|
||||
<el-table-column label="ID" align="center" prop="articleId" width="80"/>
|
||||
<el-table-column label="标题" align="center" prop="title" width="300"/>
|
||||
<el-table-column label="简介" align="center" prop="introduction"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
|
||||
</el-table>
|
||||
<pagination
|
||||
:limit.sync="searchForm.pageSize"
|
||||
:page.sync="searchForm.pageNum"
|
||||
:total="total"
|
||||
@pagination="searchList">
|
||||
</pagination>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submit()">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {clone} from "@/utils";
|
||||
import { listStore } from '@/api/ss/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { UserType } from '@/utils/constants'
|
||||
import { mchListStore } from '@/api/mch/store'
|
||||
import { listArticle } from '@/api/system/article'
|
||||
|
||||
export default {
|
||||
name: "ArticleDialog",
|
||||
props: {
|
||||
// 标题
|
||||
title: {
|
||||
type: String,
|
||||
default: '选择文章'
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Array],
|
||||
default: null,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
query: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
initSelect: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
prop: {
|
||||
type: String,
|
||||
default: 'articleId'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loadTable: false,
|
||||
tableData: [],
|
||||
searchForm: {},
|
||||
total: 0,
|
||||
row: null,
|
||||
selected: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['userType'])
|
||||
},
|
||||
methods: {
|
||||
// 获取数据列表
|
||||
searchList() {
|
||||
this.loadTable = true;
|
||||
|
||||
if (this.userType === UserType.APP) {
|
||||
// mchListStore(this.searchForm).then(response => {
|
||||
// this.tableData = response.rows;
|
||||
// this.total = response.total;
|
||||
// // 刷新表格状态
|
||||
// this.$nextTick(()=>{
|
||||
// this.refreshTableSelection();
|
||||
// })
|
||||
// }).finally(() =>{
|
||||
// this.loadTable = false;
|
||||
// })
|
||||
} else {
|
||||
listArticle(this.searchForm).then(response => {
|
||||
this.tableData = response.rows;
|
||||
this.total = response.total;
|
||||
// 刷新表格状态
|
||||
this.$nextTick(()=>{
|
||||
this.refreshTableSelection();
|
||||
})
|
||||
}).finally(() =>{
|
||||
this.loadTable = false;
|
||||
})
|
||||
}
|
||||
},
|
||||
// 打开时
|
||||
open() {
|
||||
this.searchForm = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
...this.query,
|
||||
}
|
||||
|
||||
if (this.initSelect) {
|
||||
this.selected = clone(this.initSelect);
|
||||
} else {
|
||||
this.selected = [];
|
||||
}
|
||||
|
||||
this.searchList();
|
||||
},
|
||||
// 刷新表格的选中状态
|
||||
refreshTableSelection() {
|
||||
if(this.multiple){
|
||||
this.tableData.forEach(item => {
|
||||
if (this.selected.map(j => j[this.prop]).includes(item[this.prop])) {
|
||||
this.$refs.multipleTable.toggleRowSelection(item, true);
|
||||
} else {
|
||||
this.$refs.multipleTable.toggleRowSelection(item, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
// 全选
|
||||
selectionAll(val){
|
||||
let flag = val.length > 0;
|
||||
this.tableData.forEach(item => {
|
||||
if (flag && !this.selected.map(i => i[this.prop]).includes(item[this.prop])){
|
||||
this.selected.push(item);
|
||||
} else if (!flag && this.selected.map(i => i[this.prop]).includes(item[this.prop])){
|
||||
this.selected = this.selected.filter(i => i[this.prop] !== item[this.prop]);
|
||||
}
|
||||
})
|
||||
},
|
||||
// 确认选中
|
||||
submit() {
|
||||
if (this.multiple) {
|
||||
this.$emit('select', this.selected);
|
||||
} else {
|
||||
this.select(this.row);
|
||||
}
|
||||
},
|
||||
// 更换某一行的选中状态
|
||||
changeSelection(row){
|
||||
if(this.multiple){
|
||||
if (this.selected.map(i => i[this.prop]).includes(row[this.prop])){
|
||||
this.$refs.multipleTable.toggleRowSelection(row, false);
|
||||
this.selected = this.selected.filter(i => i[this.prop] !== row[this.prop]);
|
||||
}else {
|
||||
this.$refs.multipleTable.toggleRowSelection(row, true);
|
||||
this.selected.push(row);
|
||||
}
|
||||
} else {
|
||||
this.row = row;
|
||||
}
|
||||
},
|
||||
// 点击搜索
|
||||
onSearch() {
|
||||
this.searchForm.pageNum = 1;
|
||||
this.searchList();
|
||||
},
|
||||
// 关闭弹窗
|
||||
close() {
|
||||
this.$emit('update:show', false);
|
||||
this.searchForm.pageNum = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
},
|
||||
// 选中一行
|
||||
select(row) {
|
||||
if (!this.multiple) {
|
||||
if (!row) return this.$message.error('请选择一行');
|
||||
this.selected = [row];
|
||||
this.$emit('select', row);
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
195
src/components/Business/Article/ArticleInput.vue
Normal file
195
src/components/Business/Article/ArticleInput.vue
Normal file
|
@ -0,0 +1,195 @@
|
|||
<!--version: 4, 店铺选择器-->
|
||||
<!--版本更新内容:添加prop属性,修复多选-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<el-input
|
||||
v-if="multiple"
|
||||
rows="1"
|
||||
type="textarea"
|
||||
:value="inputBindValue"
|
||||
@focus="openDialog"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
readonly
|
||||
:placeholder="placeholder"/>
|
||||
<el-input
|
||||
v-else
|
||||
:value="inputBindValue"
|
||||
@focus="openDialog"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
readonly
|
||||
:placeholder="placeholder">
|
||||
<template #suffix>
|
||||
<i class="el-icon-arrow-right"/>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<article-dialog
|
||||
:show.sync="dialogShow"
|
||||
:query="query"
|
||||
:multiple="multiple"
|
||||
:init-select="selected"
|
||||
@select="onSubmit"
|
||||
:prop="prop"
|
||||
:title="title"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {isDeepEqual} from "@/utils";
|
||||
import { mapGetters } from 'vuex'
|
||||
import { UserType } from '@/utils/constants'
|
||||
import ArticleDialog from '@/components/Business/Article/ArticleDialog.vue'
|
||||
import { listArticleByIds } from '@/api/system/article'
|
||||
|
||||
export default {
|
||||
name: 'ArticleInput',
|
||||
components: { ArticleDialog },
|
||||
props:{
|
||||
// 标题
|
||||
title: {
|
||||
type: String,
|
||||
default: "选择文章"
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "点击选择文章",
|
||||
},
|
||||
// 展示值的属性
|
||||
showProp: {
|
||||
type: String,
|
||||
default: 'title'
|
||||
},
|
||||
// 选择的属性值
|
||||
prop: {
|
||||
type: String,
|
||||
default: 'articleId'
|
||||
},
|
||||
// 是否多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 双向绑定的值(为id)
|
||||
value: {
|
||||
type: [Array, String, Number],
|
||||
default: null
|
||||
},
|
||||
// 查询条件
|
||||
query: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
// 打开弹窗前
|
||||
beforeOpen: {
|
||||
type: Function,
|
||||
default: () => {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// 关闭弹窗前
|
||||
beforeClose: {
|
||||
type: Function,
|
||||
default: () => {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// 大小
|
||||
size: {
|
||||
type: String,
|
||||
default: "medium"
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 对象处理器,参数类型:对象,返回值类型:字符串
|
||||
objectParser: {
|
||||
type: Function,
|
||||
default: (obj) => {
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selected: [], // 当前选中的值
|
||||
dialogShow: false, // 展示对话框
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['userType']),
|
||||
// 显示绑定的值
|
||||
inputBindValue() {
|
||||
if (this.selected == null || this.selected.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return this.selected.map(item => item[this.showProp]).join(",");
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(nv, ov) {
|
||||
this.loadSelected(nv);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadSelected(this.value);
|
||||
},
|
||||
methods: {
|
||||
// 加载选中的值
|
||||
loadSelected(ids) {
|
||||
if (ids == null || ids.length === 0) {
|
||||
this.selected = [];
|
||||
return;
|
||||
}
|
||||
if (ids instanceof Array) {
|
||||
this.doLoad(ids);
|
||||
} else {
|
||||
this.doLoad([ids]);
|
||||
}
|
||||
},
|
||||
// 加载选中值
|
||||
doLoad(ids) {
|
||||
if (this.userType === UserType.APP) {
|
||||
} else {
|
||||
listArticleByIds(ids).then(res => {
|
||||
this.selected = res.data;
|
||||
})
|
||||
}
|
||||
},
|
||||
// 修改值
|
||||
inputValue(val){
|
||||
this.$emit('input', val);
|
||||
},
|
||||
// 确定
|
||||
onSubmit(selected){
|
||||
let value = null;
|
||||
if (this.multiple) {
|
||||
value = selected.map(item => item[this.prop]);
|
||||
} else {
|
||||
value = selected[this.prop];
|
||||
}
|
||||
this.$emit('submit', selected);
|
||||
if (!isDeepEqual(this.value, value)) {
|
||||
this.$emit('change', selected);
|
||||
}
|
||||
this.inputValue(value);
|
||||
this.closeDialog();
|
||||
},
|
||||
closeDialog() {
|
||||
if (this.beforeClose()) {
|
||||
this.dialogShow = false;
|
||||
}
|
||||
},
|
||||
// 打开对话框
|
||||
openDialog(){
|
||||
if (this.beforeOpen()) {
|
||||
this.dialogShow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -86,7 +86,7 @@ export default {
|
|||
},
|
||||
prop: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
default: 'storeId'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -108,7 +108,7 @@ export default {
|
|||
this.loadTable = true;
|
||||
|
||||
if (this.userType === UserType.APP) {
|
||||
mchListStore().then(response => {
|
||||
mchListStore(this.searchForm).then(response => {
|
||||
this.tableData = response.rows;
|
||||
this.total = response.total;
|
||||
// 刷新表格状态
|
||||
|
@ -119,7 +119,7 @@ export default {
|
|||
this.loadTable = false;
|
||||
})
|
||||
} else {
|
||||
listStore.then(response => {
|
||||
listStore(this.searchForm).then(response => {
|
||||
this.tableData = response.rows;
|
||||
this.total = response.total;
|
||||
// 刷新表格状态
|
||||
|
|
|
@ -136,3 +136,19 @@ export const RecordTimeOperatorType = {
|
|||
ADMIN: '1', // 管理员
|
||||
USER: '2', // 用户
|
||||
}
|
||||
|
||||
// 系统参数KEY
|
||||
export const ConfigKey = {
|
||||
SERVICE_FEE_RATE: "sm.transactionBill.serviceFee", // 充值服务费费率
|
||||
WECHAT_APPROVAL: "sys.wechat.approval", // 微信小程序敏感内容展示
|
||||
DAILY_WITHDRAW_AMOUNT: "daily.withdraw.amount", // 单日单用户提现限额(元)
|
||||
DAILY_WITHDRAW_COUNT: "daily.withdraw.count", // 单日单用户提现次数(次)
|
||||
NOVERIFY_WITHDRAW_SINGLE: "noverify.withdraw.single", // 提现单笔免审核额度(元)
|
||||
RECHARGE_MIN_SERVICE: "recharge.min.service", // 充值最低服务费(元)
|
||||
ORDER_AUTO_CLOSE_CD: "order.auto.close.cd", // 订单自动关闭冷却时间(分)
|
||||
SS_LICENCE_USER_ID: "ss.licence.user.id", // 用户协议文章ID
|
||||
SS_LICENCE_PRIVACY_ID: "ss.licence.privacy.id", // 隐私政策文章ID
|
||||
SS_LICENCE_ABOUT_ID: "ss.licence.about.id", // 关于我们文章ID
|
||||
SS_LICENCE_MCH_ID: "ss.licence.mch.id", // 商户协议文章ID
|
||||
SS_LICENCE_COLLECTION_ID: "ss.licence.collection.id", // 个人信息收集清单文章ID
|
||||
}
|
||||
|
|
66
src/views/system/config/components/ConfigItem.vue
Normal file
66
src/views/system/config/components/ConfigItem.vue
Normal file
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<el-form :model="config" inline ref="form" size="medium" v-if="hasPermission">
|
||||
<el-form-item :label="config.configName" :label-width="(config.configName.length + 1) + 'em'" prop="configValue">
|
||||
<slot :row="config">
|
||||
<el-input v-model="config.configValue" :placeholder="`请输入${config.configName}`"/>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleSubmit" type="primary" :loading="loading" icon="el-icon-check" size="small">修改</el-button>
|
||||
<slot name="remark">
|
||||
<span v-if="config.remark" style="font-size: 12px;color: #606060;margin-left: 1em;">{{config.remark}}</span>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { batchUpdateConfigValue } from '@/api/system/config'
|
||||
import { checkPermi } from '@/utils/permission'
|
||||
import { isEmpty } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: "ConfigItem",
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 判断是否有权限
|
||||
hasPermission() {
|
||||
if (this.config == null || isEmpty(this.config.permission)) {
|
||||
return true;
|
||||
}
|
||||
return checkPermi([this.config.permission]);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
batchUpdateConfigValue([this.config]).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message.success('修改成功')
|
||||
this.$emit('success');
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
87
src/views/system/config/group.vue
Normal file
87
src/views/system/config/group.vue
Normal file
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<div class="app-container" v-loading="loading">
|
||||
<el-tabs tab-position="left">
|
||||
<el-tab-pane label="充值/提现配置" lazy>
|
||||
<h3>充值</h3>
|
||||
<config-item :config="getConfig(ConfigKey.RECHARGE_MIN_SERVICE)"/>
|
||||
<config-item :config="getConfig(ConfigKey.ORDER_AUTO_CLOSE_CD)"/>
|
||||
<h3>提现</h3>
|
||||
<config-item :config="getConfig(ConfigKey.DAILY_WITHDRAW_AMOUNT)"/>
|
||||
<config-item :config="getConfig(ConfigKey.DAILY_WITHDRAW_COUNT)"/>
|
||||
<config-item :config="getConfig(ConfigKey.NOVERIFY_WITHDRAW_SINGLE)"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="文章配置" lazy>
|
||||
<config-item :config="getConfig(ConfigKey.SS_LICENCE_USER_ID)">
|
||||
<article-input slot-scope="d" v-model="d.row.configValue"/>
|
||||
</config-item>
|
||||
<config-item :config="getConfig(ConfigKey.SS_LICENCE_PRIVACY_ID)">
|
||||
<article-input slot-scope="d" v-model="d.row.configValue"/>
|
||||
</config-item>
|
||||
<config-item :config="getConfig(ConfigKey.SS_LICENCE_ABOUT_ID)">
|
||||
<article-input slot-scope="d" v-model="d.row.configValue"/>
|
||||
</config-item>
|
||||
<config-item :config="getConfig(ConfigKey.SS_LICENCE_COLLECTION_ID)">
|
||||
<article-input slot-scope="d" v-model="d.row.configValue"/>
|
||||
</config-item>
|
||||
<config-item :config="getConfig(ConfigKey.SS_LICENCE_MCH_ID)">
|
||||
<article-input slot-scope="d" v-model="d.row.configValue"/>
|
||||
</config-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { getConfigKeys } from '@/api/system/config'
|
||||
import { ConfigKey } from '@/utils/constants'
|
||||
import ConfigItem from '@/views/system/config/components/ConfigItem.vue'
|
||||
import ArticleInput from '@/components/Business/Article/ArticleInput.vue'
|
||||
|
||||
export default {
|
||||
name: "GroupConfig",
|
||||
components: { ArticleInput, ConfigItem },
|
||||
data() {
|
||||
return {
|
||||
ConfigKey,
|
||||
keys: Object.values(ConfigKey),
|
||||
map: {},
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
getConfig(key) {
|
||||
let config = this.map[key];
|
||||
if (config == null) {
|
||||
return {
|
||||
configName: '加载中'
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getConfigKeys(this.keys).then(res => {
|
||||
let list = res.data;
|
||||
let map = {};
|
||||
list.forEach(item => {
|
||||
map[item.configKey] = item;
|
||||
})
|
||||
this.map = map;
|
||||
console.log(this.map)
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-tabs__content {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user