修改红包等
This commit is contained in:
@@ -0,0 +1,249 @@
|
|||||||
|
<template>
|
||||||
|
<el-form
|
||||||
|
ref="form"
|
||||||
|
:label-width="labelWidth"
|
||||||
|
label-position="right"
|
||||||
|
size="medium"
|
||||||
|
:model="formData"
|
||||||
|
inline
|
||||||
|
:rules="rules"
|
||||||
|
:inline-message="false">
|
||||||
|
<el-form-item
|
||||||
|
v-for="(item, i) in formItems"
|
||||||
|
:key="i"
|
||||||
|
:style="{ width: item.width }"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.key">
|
||||||
|
<div :style="{ width: item.contentWidth || contentWidth }">
|
||||||
|
<el-date-picker
|
||||||
|
v-if="item.type === 'date'"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
type="date"
|
||||||
|
size="normal"
|
||||||
|
placeholder="请选择日期"></el-date-picker>
|
||||||
|
<el-input-number
|
||||||
|
v-else-if="item.type === 'number'"
|
||||||
|
:style="{ width: item.width || '192px' }"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
size="small"
|
||||||
|
:min="0"
|
||||||
|
:placeholder="placeholderWidthFormItem(item)"></el-input-number>
|
||||||
|
<el-switch
|
||||||
|
v-else-if="item.type === 'switch'"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
:disabled="item.disabled"></el-switch>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'select'"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
:placeholder="placeholderWidthFormItem(item)"
|
||||||
|
size="small"
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="(option, index) in item.options"
|
||||||
|
:key="index"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<!-- <base-upload
|
||||||
|
v-else-if="item.type === 'image'"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
:hide="true"
|
||||||
|
width="100px"
|
||||||
|
height="100px"
|
||||||
|
></base-upload>
|
||||||
|
<imgs-upload
|
||||||
|
ref="imgsUpload"
|
||||||
|
v-else-if="item.type === 'images'"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
:hide="true"
|
||||||
|
width="100px"
|
||||||
|
height="100px"
|
||||||
|
></imgs-upload>
|
||||||
|
<TagSelector
|
||||||
|
v-else-if="item.type === 'tags'"
|
||||||
|
:style="{ width: item.width || '350px' }"
|
||||||
|
:tag-list="tagList"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
></TagSelector> -->
|
||||||
|
<el-input
|
||||||
|
v-else
|
||||||
|
:type="item.type"
|
||||||
|
v-model="formData[item.key]"
|
||||||
|
:placeholder="item.placeholder || placeholderWidthFormItem(item)"
|
||||||
|
clearable
|
||||||
|
size="small"></el-input>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<slot></slot>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TagSelector from '../tagSelector.vue'
|
||||||
|
import baseUpload from '../baseUpload.vue'
|
||||||
|
import ImgsUpload from '../imgsUpload.vue'
|
||||||
|
import API from '@/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ConfigForms',
|
||||||
|
components: { baseUpload, ImgsUpload, TagSelector },
|
||||||
|
props: {
|
||||||
|
labelWidth: {
|
||||||
|
type: String,
|
||||||
|
default: '80px'
|
||||||
|
},
|
||||||
|
contentWidth: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Array<FormItem>
|
||||||
|
* FormItem:
|
||||||
|
* - label: string
|
||||||
|
* - key: string | number
|
||||||
|
* - required: bool
|
||||||
|
* - type?: 'select' | 'date' | 'text' | 'textarea' | 'number' | 'tags'
|
||||||
|
* - options?: FormOption[]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* FormOption:
|
||||||
|
* - label: string
|
||||||
|
* - value: string | number
|
||||||
|
*/
|
||||||
|
formItems: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {},
|
||||||
|
tagList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
rules() {
|
||||||
|
const rs = {}
|
||||||
|
this.formItems.forEach((item) => {
|
||||||
|
rs[item.key] = [
|
||||||
|
{
|
||||||
|
required: !!item.required,
|
||||||
|
message: this.placeholderWidthFormItem(item)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
return rs
|
||||||
|
},
|
||||||
|
containTags() {
|
||||||
|
return this.formItems.findIndex((v) => v.type === 'tags') >= 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
formItems: {
|
||||||
|
handler() {
|
||||||
|
this.setFormDataDefault()
|
||||||
|
this.getTagList()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
handler(val, oldVal) {
|
||||||
|
let isSame = false
|
||||||
|
if (val && oldVal) {
|
||||||
|
isSame = val.id === oldVal.id
|
||||||
|
}
|
||||||
|
if (this.$refs.imgsUpload && !isSame) {
|
||||||
|
this.$refs.imgsUpload.forEach((el) => el.clearImg())
|
||||||
|
}
|
||||||
|
if (val && Object.keys(val).length) {
|
||||||
|
this.assign(this.formData, val, 'entry')
|
||||||
|
} else {
|
||||||
|
// Object.keys(this.formData).forEach(
|
||||||
|
// (key) => {
|
||||||
|
// this.formData[key] = null
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
formData: {
|
||||||
|
handler(val) {
|
||||||
|
this.$emit('change', val)
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async validate() {
|
||||||
|
await this.$refs.form.validate()
|
||||||
|
const data = {}
|
||||||
|
this.assign(data, this.formData, 'output')
|
||||||
|
return data
|
||||||
|
},
|
||||||
|
assign(target, source, type) {
|
||||||
|
Object.keys(source).forEach((key) => {
|
||||||
|
const itemVal = source[key]
|
||||||
|
const config = this.formItems.find((v) => v.key === key)
|
||||||
|
if (config) {
|
||||||
|
const func = config[type]
|
||||||
|
target[key] = func ? func(itemVal) : itemVal
|
||||||
|
} else {
|
||||||
|
target[key] = itemVal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
placeholderWidthFormItem(item) {
|
||||||
|
const prefix = {
|
||||||
|
select: '请选择',
|
||||||
|
date: '请选择',
|
||||||
|
text: '请输入',
|
||||||
|
number: '请输入',
|
||||||
|
tags: '请选择',
|
||||||
|
switch: '请选择',
|
||||||
|
image: '请上传',
|
||||||
|
images: '请上传'
|
||||||
|
}
|
||||||
|
const cur = prefix[item.type] || '请输入'
|
||||||
|
return cur + item.label
|
||||||
|
},
|
||||||
|
|
||||||
|
setFormDataDefault() {
|
||||||
|
this.formItems.forEach((v) => {
|
||||||
|
this.$set(this.formData, v.key, null)
|
||||||
|
})
|
||||||
|
if (this.containTags) {
|
||||||
|
this.$set(this.formData, 'tags', [])
|
||||||
|
// this.formData.tags = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getTagList() {
|
||||||
|
if (!this.containTags) return
|
||||||
|
if (this.tagList && this.tagList.length > 0) return
|
||||||
|
const params = {}
|
||||||
|
API.queryTagList(params).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.tagList = res.data.list || []
|
||||||
|
console.log(this.tagList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -0,0 +1,357 @@
|
|||||||
|
<template>
|
||||||
|
<div class="config-table">
|
||||||
|
<!-- search area -->
|
||||||
|
<el-form class="config-table__search" size="mini" inline>
|
||||||
|
<el-form-item
|
||||||
|
v-for="item in searchConfig"
|
||||||
|
:key="item.key"
|
||||||
|
:label="item.label">
|
||||||
|
<el-input
|
||||||
|
v-if="item.type === 'input'"
|
||||||
|
size="small"
|
||||||
|
v-model="params[item.key]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
clearable
|
||||||
|
@blur="inputBlur"
|
||||||
|
@focus="inputFocus"></el-input>
|
||||||
|
<el-input
|
||||||
|
v-else-if="item.type === 'number'"
|
||||||
|
:style="{ width: item.width || '192px' }"
|
||||||
|
v-model.number="params[item.key]"
|
||||||
|
size="small"
|
||||||
|
:min="item.min"
|
||||||
|
:max="item.max"
|
||||||
|
:placeholder="item.placeholder"></el-input>
|
||||||
|
<el-select
|
||||||
|
v-else-if="item.type === 'select'"
|
||||||
|
size="small"
|
||||||
|
v-model="params[item.key]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="op in item.options"
|
||||||
|
:key="op.value"
|
||||||
|
:value="op.value"
|
||||||
|
:label="op.label"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-date-picker
|
||||||
|
v-if="item.type.startsWith('date')"
|
||||||
|
v-model="params[item.key]"
|
||||||
|
:type="item.type"
|
||||||
|
size="small"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:start-placeholder="item.startPlaceholder"
|
||||||
|
:end-placeholder="item.endPlaceholder"
|
||||||
|
:clearable="item.clearable === undefined ? true : item.clearable"></el-date-picker>
|
||||||
|
<el-button
|
||||||
|
v-else-if="item.type === 'button' && !item.hidden"
|
||||||
|
:disabled="item.isBatch && !isBatchButtonEnable"
|
||||||
|
type="primary"
|
||||||
|
:icon="`el-icon-${item.icon}`"
|
||||||
|
size="small"
|
||||||
|
@click="buttonAction(item)">{{ item.placeholder }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<!-- table area -->
|
||||||
|
<div class="config-table__table">
|
||||||
|
<el-table
|
||||||
|
height="100%"
|
||||||
|
ref="table"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
@selection-change="selectChange">
|
||||||
|
<el-table-column
|
||||||
|
v-if="isSelection"
|
||||||
|
type="selection"
|
||||||
|
width="40"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
:key="column.id"
|
||||||
|
:min-width="column.width || 160"
|
||||||
|
align="center"
|
||||||
|
:label="column.name"
|
||||||
|
:prop="column.key"
|
||||||
|
:fixed="column.fixed">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-if="column.actions" class="table-column-actions">
|
||||||
|
<div v-for="(action, i) in column.actions" :key="i">
|
||||||
|
<el-button
|
||||||
|
:class="{ isNullText: !action.text }"
|
||||||
|
v-if="action.hidden ? !action.hidden(scope.row) : true"
|
||||||
|
:type="action | getTagStyle"
|
||||||
|
:icon="`el-icon-${action.key || action}`"
|
||||||
|
size="mini"
|
||||||
|
@click="rowAction(action, scope.row)">{{ action.text }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="column.overflowTooltip2"
|
||||||
|
class="table-column-actions">
|
||||||
|
<el-tooltip :content="scope.row[column.key]" placement="top">
|
||||||
|
<p class="descStyle">{{ scope.row[column.key] }}</p>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="column.component">
|
||||||
|
<component
|
||||||
|
:is="column.component"
|
||||||
|
v-bind="
|
||||||
|
typeof column.props === 'function'
|
||||||
|
? column.props(scope.row[column.key], scope.row)
|
||||||
|
: column.props
|
||||||
|
">
|
||||||
|
{{
|
||||||
|
column.valueHandler
|
||||||
|
? column.valueHandler(
|
||||||
|
scope.row[column.key],
|
||||||
|
scope.row,
|
||||||
|
column.key
|
||||||
|
)
|
||||||
|
: scope.row[column.key]
|
||||||
|
}}</component>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
{{
|
||||||
|
column.valueHandler
|
||||||
|
? column.valueHandler(
|
||||||
|
scope.row[column.key],
|
||||||
|
scope.row,
|
||||||
|
column.key
|
||||||
|
)
|
||||||
|
: scope.row[column.key] || "-"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<!-- pagination area -->
|
||||||
|
<div v-if="this.params.pageSize" class="pagination-footer">
|
||||||
|
<el-pagination
|
||||||
|
:page-sizes="pageSizes"
|
||||||
|
:current-page.sync="params.pageNumber"
|
||||||
|
:page-size.sync="params.pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
background></el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ConfigTable',
|
||||||
|
props: {
|
||||||
|
searchConfig: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tableColumns: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
pageSizes: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [5, 10, 15, 20, 50, 100]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
defaultParams: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
pageNumber: 1,
|
||||||
|
pageSize: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
params: {
|
||||||
|
...this.defaultParams
|
||||||
|
},
|
||||||
|
selectedData: [],
|
||||||
|
isInputFocus: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// Object.keys(this.defaultParams).forEach(key => {
|
||||||
|
// this.$set(this.params, key, this.defaultParams[key])
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isSelection() {
|
||||||
|
return (
|
||||||
|
this.selection || this.searchConfig.findIndex((v) => v.isBatch) > -1
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isBatchButtonEnable() {
|
||||||
|
return this.selectedData.length > 0
|
||||||
|
},
|
||||||
|
// clearSelection 用于多选表格,清空用户的选择 —
|
||||||
|
// toggleRowSelection 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中) row, selected
|
||||||
|
// toggleAllSelection 用于多选表格,切换所有行的选中状态 -
|
||||||
|
// toggleRowExpansion 用于可展开表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expanded 为 true 则展开) row, expanded
|
||||||
|
// setCurrentRow 用于单选表格,设定某一行为选中行,如果调用时不加参数,则会取消目前高亮行的选中状态。 row
|
||||||
|
// clearSort 用于清空排序条件,数据会恢复成未排序的状态 —
|
||||||
|
// clearFilter 用于清空过滤条件,数据会恢复成未过滤的状态 —
|
||||||
|
// doLayout 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法 —
|
||||||
|
// sort 手动对 Table 进行排序。参数prop属性指定排序列,order指定排序顺序。 prop: string, order: string
|
||||||
|
// name 说明
|
||||||
|
// append 插入至表格最后一行之后的内容,如果需要对表格的内容进行无限滚动操作,可能需要用到这个 slot。若表格有合计行,该 slot 会位于合计行之上。
|
||||||
|
table() {
|
||||||
|
return this.$refs.table
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
params: {
|
||||||
|
handler() {
|
||||||
|
// / 输入框改变做防抖处理
|
||||||
|
// this.isInputFocus ? this.debounceSearch() : this.search()
|
||||||
|
this.debounceSearch()
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
search() {
|
||||||
|
const params = {}
|
||||||
|
Object.keys(this.params).forEach((key) => {
|
||||||
|
params[key] = this.params[key]
|
||||||
|
if (Array.isArray(this.params[key])) {
|
||||||
|
const config = this.searchConfig.find((v) => v.key === key)
|
||||||
|
if (config && Array.isArray(config.keys)) {
|
||||||
|
config.keys.forEach((k, i) => (params[k] = this.params[key][i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$emit('change', params)
|
||||||
|
},
|
||||||
|
debounceSearch: debounce(function() {
|
||||||
|
this.search()
|
||||||
|
}, 500),
|
||||||
|
inputFocus() {
|
||||||
|
this.isInputFocus = true
|
||||||
|
},
|
||||||
|
inputBlur() {
|
||||||
|
this.isInputFocus = false
|
||||||
|
},
|
||||||
|
buttonAction(item) {
|
||||||
|
if (this.buttonLocakTimeout) {
|
||||||
|
clearTimeout(this.buttonLocakTimeout)
|
||||||
|
}
|
||||||
|
this.buttonLocakTimeout = setTimeout(() => {
|
||||||
|
this.buttonLock = false
|
||||||
|
}, 500)
|
||||||
|
if (this.buttonLock) return
|
||||||
|
this.buttonLock = true
|
||||||
|
|
||||||
|
if (item.isBatch) {
|
||||||
|
this.rowAction(item.key, this.selectedData)
|
||||||
|
} else {
|
||||||
|
this.rowAction(item.key)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowAction(action, row) {
|
||||||
|
if (typeof this[action] === 'function') {
|
||||||
|
// eslint-disable-next-line no-useless-call
|
||||||
|
return this[action].call(this, row)
|
||||||
|
}
|
||||||
|
this.$emit(action.action || action, row)
|
||||||
|
},
|
||||||
|
selectChange(e) {
|
||||||
|
this.selectedData = e
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
getTagStyle(idx) {
|
||||||
|
idx = idx.key || idx
|
||||||
|
if (idx === 'edit') return 'success'
|
||||||
|
if (idx === 'delete') return 'danger'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.config-table {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: calc(100vh - 140px);
|
||||||
|
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__table {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
/deep/ .el-button--mini {
|
||||||
|
padding: 7px 11px !important;
|
||||||
|
font-weight: normal !important;
|
||||||
|
&.isNullText {
|
||||||
|
span {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-column-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-footer {
|
||||||
|
z-index: 100;
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
height: 60px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
background: #ebe5e1;
|
||||||
|
|
||||||
|
/deep/ .el-pagination {
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.descStyle {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2; /* 限制最多显示 2 行 */
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -34,6 +34,10 @@ export function comicsTopicshowTypeList () {
|
|||||||
}, {
|
}, {
|
||||||
label: '竖列表',
|
label: '竖列表',
|
||||||
value: 7
|
value: 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '横滑3宫格',
|
||||||
|
value: 13
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -831,6 +831,18 @@ export const serverRouter = [
|
|||||||
icon: 'el-icon-chat-dot-square'
|
icon: 'el-icon-chat-dot-square'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'hongbao',
|
||||||
|
name: 'Hongbao',
|
||||||
|
api_url: [],
|
||||||
|
meta: { title: '红包配置管理', noCache: true, icon: 'el-icon-chat-dot-square' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'hongbaoList',
|
||||||
|
name: 'HongbaoList',
|
||||||
|
api_url: [],
|
||||||
|
meta: { title: '红包领取记录', noCache: true, icon: 'el-icon-chat-dot-square' }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'advertise',
|
path: 'advertise',
|
||||||
name: 'Advertise',
|
name: 'Advertise',
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ const map = {
|
|||||||
// 活动管理
|
// 活动管理
|
||||||
Activity: Layout,
|
Activity: Layout,
|
||||||
Announcement: () => import('@/views/activity/announcement/index.vue'), // 公告列表
|
Announcement: () => import('@/views/activity/announcement/index.vue'), // 公告列表
|
||||||
|
Hongbao: () => import('@/views/activity/hongbao/index.vue'), // 红包管理
|
||||||
|
HongbaoList: () => import('@/views/activity/hongbao/list.vue'), // 红包领取记录
|
||||||
Advertise: () => import('@/views/activity/advertise/index.vue'), // 活动广告
|
Advertise: () => import('@/views/activity/advertise/index.vue'), // 活动广告
|
||||||
CardActivity: () => import('@/views/activity/cardActivity/index.vue'), // 集卡活动
|
CardActivity: () => import('@/views/activity/cardActivity/index.vue'), // 集卡活动
|
||||||
CardcolletList: () => import('@/views/activity/cardcolletList/index.vue'), // 抽卡结果列表
|
CardcolletList: () => import('@/views/activity/cardcolletList/index.vue'), // 抽卡结果列表
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog :title="title" :visible.sync="Visible" width="700px" center class="ac-dialog" :close-on-click-modal="false" @close="close">
|
||||||
|
<el-form :inline="true" :rules="rules" :model="form" ref="ruleForm" class="demo-form-inline" label-width="150px" label-position="right">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="用户Id" prop="userId">
|
||||||
|
<el-input placeholder="请输入用户Id" v-model="form.userId" style="width: 400px" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="图片">
|
||||||
|
<UploadImg @changeImgUrl="changeCoverImgUrl" @onRemove="onRemoveImage('img', $event)" :img="form.img"></UploadImg>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="系统消息标题">
|
||||||
|
<el-input placeholder="请输入系统消息标题" v-model="form.title" style="width: 400px" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="跳转链接" prop="content">
|
||||||
|
<el-input placeholder="请输入跳转链接" v-model="form.link" style="width: 400px" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="内容" prop="content">
|
||||||
|
<el-input placeholder="请输入内容" v-model="form.content" type="textarea" style="width: 400px" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="Visible = false"> 取 消 </el-button>
|
||||||
|
<el-button type="primary" @click="submit('ruleForm')"> 确 定 </el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment'
|
||||||
|
import UploadImg from '@/components/UploadImg/index'
|
||||||
|
import { msgAdd, msgUpdate } from '@/api/activity/msg'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AddOrEdit',
|
||||||
|
props: ['data'],
|
||||||
|
components: {
|
||||||
|
UploadImg
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
Visible: true,
|
||||||
|
title: '',
|
||||||
|
// 表单数据
|
||||||
|
form: {
|
||||||
|
img: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
content: undefined, // "string",内容
|
||||||
|
title: undefined // "string",标题
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
content: [{ required: true, message: '必填', trigger: 'blur' }],
|
||||||
|
userId: [{ required: true, message: '必填', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.title = this.data.title
|
||||||
|
if (this.title === '编辑') {
|
||||||
|
this.form = { ...this.data.data }
|
||||||
|
this.form.start = moment(this.data.data.start).utcOffset(480).format('YYYY-MM-DDTHH:mm:ss') + '+08:00'
|
||||||
|
this.form.end = moment(this.data.data.end).utcOffset(480).format('YYYY-MM-DDTHH:mm:ss') + '+08:00'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// TODO:新增消息列表数据
|
||||||
|
add(data) {
|
||||||
|
msgAdd(data).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$message.success('新增成功')
|
||||||
|
this.Visible = false
|
||||||
|
} else {
|
||||||
|
this.$message.error('新增失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// TODO:编辑消息列表数据
|
||||||
|
update(data) {
|
||||||
|
msgUpdate(data).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$message.success('更新成功')
|
||||||
|
this.Visible = false
|
||||||
|
} else {
|
||||||
|
this.$message.error('更新失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changeCoverImgUrl(data) {
|
||||||
|
this.form.img = data
|
||||||
|
},
|
||||||
|
// 移除图片地址到form表单
|
||||||
|
onRemoveImage(key, type) {
|
||||||
|
if (type) {
|
||||||
|
this.form[key].type = ''
|
||||||
|
} else {
|
||||||
|
this.form[key] = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 提交按钮
|
||||||
|
submit(formName) {
|
||||||
|
this.$refs[formName].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.form.userId = +this.form.userId
|
||||||
|
const data = { ...this.form }
|
||||||
|
if (this.title === '新增') {
|
||||||
|
this.add(data)
|
||||||
|
} else if (this.title === '编辑') {
|
||||||
|
this.update(data)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关闭编辑
|
||||||
|
close() {
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hongbao-bg">
|
||||||
|
<el-form :inline="true" :model="form" ref="ruleForm" label-width="150px" label-position="right">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="展示开启" prop="enabled">
|
||||||
|
<el-switch v-model="form.enabled" active-color="#13ce66" inactive-color="#ff4949" active-text="开启"
|
||||||
|
inactive-text="关闭"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item label="发放金币总数" prop="content">
|
||||||
|
<el-input placeholder="请输入总数" v-model.number="form.dailyLimit" style="width: 400px">
|
||||||
|
<template #append>
|
||||||
|
<span>金币</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
<el-form-item :label="`第${i + 1}次领取`" size="mini" v-for="(ru, i) in form.rule" :key="i">
|
||||||
|
<el-form-item label="间隔:" size="mini" label-width="50">
|
||||||
|
<el-input placeholder="单位(s)" v-model.number="ru.interval" style="width: 120px">
|
||||||
|
<template #append>
|
||||||
|
<span>秒</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最小:" size="mini" label-width="50">
|
||||||
|
<el-input placeholder="该次领取最小值" v-model.number="ru.min" style="width: 150px">
|
||||||
|
<template #append>
|
||||||
|
<span>金币</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最大:" size="mini" label-width="50">
|
||||||
|
<el-input placeholder="该次领取最大值" v-model.number="ru.max" style="width: 150px">
|
||||||
|
<template #append>
|
||||||
|
<span>金币</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-button icon="el-icon-delete" type="danger" size="mini" @click="delRule(i)"></el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div style="margin-left: 100px;">
|
||||||
|
<el-button type="text" icon="el-icon-circle-plus-outline" @click="addRule">新增规则</el-button>
|
||||||
|
<el-button type="primary" @click="submit"> 确 定 </el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { updateConfig, getConfig } from '@/api/activity/msg'
|
||||||
|
export default {
|
||||||
|
name: 'Hongbao',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
enabled: true,
|
||||||
|
interval: 600,
|
||||||
|
dailyLimit: 200,
|
||||||
|
rule: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isLastRuleAvailable() {
|
||||||
|
if (!this.form.rule || !this.form.rule.length) return true
|
||||||
|
const lastRule = this.form.rule[this.form.rule.length - 1]
|
||||||
|
return lastRule.interval && lastRule.min && lastRule.max
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async init() {
|
||||||
|
const res = await getConfig()
|
||||||
|
this.form = res.data
|
||||||
|
this.form.dailyLimit = (res.data.dailyLimit || 0) / 100
|
||||||
|
if (this.form.rule) {
|
||||||
|
this.form.rule = this.form.rule.map(v => ({ ...v, min: v.min / 100, max: v.max / 100 }))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
if (!this.isLastRuleAvailable) {
|
||||||
|
this.$message.error('请完善最后一项规则或者删除')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const form = {
|
||||||
|
...this.form,
|
||||||
|
dailyLimit: this.form.dailyLimit * 100
|
||||||
|
}
|
||||||
|
if (this.form.rule) {
|
||||||
|
form.rule = this.form.rule.map(v => ({ ...v, min: v.min * 100, max: v.max * 100 }))
|
||||||
|
}
|
||||||
|
await updateConfig(form)
|
||||||
|
this.$message.success('修改成功')
|
||||||
|
},
|
||||||
|
addRule() {
|
||||||
|
if (!this.isLastRuleAvailable) {
|
||||||
|
this.$message.error('请先完善上一项规则')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rule = {
|
||||||
|
min: null,
|
||||||
|
max: null,
|
||||||
|
interval: null
|
||||||
|
}
|
||||||
|
this.form.rule = this.form.rule || []
|
||||||
|
this.form.rule.push(rule)
|
||||||
|
},
|
||||||
|
delRule(i) {
|
||||||
|
this.form.rule.splice(i, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.hongbao-bg {
|
||||||
|
height: 80vh;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 50px 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hongbao-list">
|
||||||
|
<ConfigTable
|
||||||
|
ref="ct"
|
||||||
|
:searchConfig="searchConfig"
|
||||||
|
:tableColumns="tableColumns"
|
||||||
|
:tableData="list"
|
||||||
|
:total="total"
|
||||||
|
@change="loadData"
|
||||||
|
@delete="delRow"
|
||||||
|
@edit="editRow"></ConfigTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ConfigTable from '@/components/ConfigTable'
|
||||||
|
import { getRecordList } from '@/api/activity/msg'
|
||||||
|
import { BeiJingTime } from '@/filters'
|
||||||
|
|
||||||
|
const prizeTypeOptions = [
|
||||||
|
{ label: '金币', value: 1 },
|
||||||
|
{ label: '积分', value: 2 }
|
||||||
|
]
|
||||||
|
|
||||||
|
const searchConfig = [
|
||||||
|
{ type: 'number', placeholder: '输入用户ID查询', key: 'userId' },
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
placeholder: '奖励类型',
|
||||||
|
key: 'prizeType',
|
||||||
|
options: prizeTypeOptions
|
||||||
|
},
|
||||||
|
// { type: "date", placeholder: "请选择日期", key: "day", format: 'YYYY-MM-DD' },
|
||||||
|
{ type: 'daterange', startPlaceholder: '开始日期', endPlaceholder: '结束日期', key: 'startTimeAndEndTime', keys: ['startTime', 'endTime'], format: 'YYYY-MM-DD' },
|
||||||
|
{ type: 'button', icon: 'search', placeholder: '搜索', key: 'search' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const tableColumns = (_this) => [
|
||||||
|
{ name: 'id', key: 'id', fixed: 'fixed' },
|
||||||
|
{ name: '用户id', key: 'userId', fixed: 'fixed' },
|
||||||
|
{ name: '用户昵称', key: 'nickname' },
|
||||||
|
{ name: '日期', key: 'day' },
|
||||||
|
{ name: '奖励类型', key: 'prizeType', valueHandler: (val) => (prizeTypeOptions.find(v => v.value == val) || {}).label },
|
||||||
|
{ name: '奖励数量(金币)', key: 'amount', valueHandler: (val) => val / 100 },
|
||||||
|
{ name: '领取时间', key: 'createdAt', valueHandler: (val) => BeiJingTime(val) }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HongbaoList',
|
||||||
|
components: { ConfigTable },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchConfig,
|
||||||
|
total: 0,
|
||||||
|
list: [],
|
||||||
|
appOpts: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tableColumns() {
|
||||||
|
return tableColumns(this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {},
|
||||||
|
mounted() { },
|
||||||
|
methods: {
|
||||||
|
async loadData(params) {
|
||||||
|
try {
|
||||||
|
const newParams = {}
|
||||||
|
Object.keys(params).forEach((key) => {
|
||||||
|
if (params[key] !== '') newParams[key] = params[key]
|
||||||
|
})
|
||||||
|
const r = await getRecordList(newParams)
|
||||||
|
const data = r.data
|
||||||
|
this.total = data.total
|
||||||
|
this.list = data.list
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async delRow(row) {
|
||||||
|
try {
|
||||||
|
await this.$confirm('您确定要删除该条数据吗?', '操作提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
const r = await transApi.delAiTextImage({ id: row.id })
|
||||||
|
if (r.code === 200) {
|
||||||
|
this.$message.success('已删除')
|
||||||
|
this.$refs.ct.search()
|
||||||
|
} else {
|
||||||
|
this.$message.error(r.tip)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async editRow(row) {
|
||||||
|
this.$refs.editDialog.open(row)
|
||||||
|
},
|
||||||
|
async callEdit(r) {
|
||||||
|
try {
|
||||||
|
console.log(r)
|
||||||
|
const res = await transApi.updateAiTextImage(r.data)
|
||||||
|
if (res.code !== 200) {
|
||||||
|
this.$message.error(res.data)
|
||||||
|
} else {
|
||||||
|
this.$message.success(r.isEdit ? '退款成功' : '')
|
||||||
|
this.$refs.editDialog.close()
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.ct.search()
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('call edit error:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -16,6 +16,13 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :lg="24" :md="24" :sm="24" :xl="24" :xs="24">
|
||||||
|
<el-form-item label="跳转链接">
|
||||||
|
<el-input v-model="form.jumpLink" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="dialog-footer" slot="footer">
|
<div class="dialog-footer" slot="footer">
|
||||||
<el-button @click="Visible=false">取 消</el-button>
|
<el-button @click="Visible=false">取 消</el-button>
|
||||||
@@ -37,7 +44,8 @@ export default {
|
|||||||
// 表单数据
|
// 表单数据
|
||||||
form: {
|
form: {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
topRank: undefined
|
topRank: undefined,
|
||||||
|
jumpLink: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53,7 +61,8 @@ export default {
|
|||||||
const param = {
|
const param = {
|
||||||
id: this.form.id,
|
id: this.form.id,
|
||||||
param: {
|
param: {
|
||||||
topRank: this.form.topRank
|
topRank: this.form.topRank,
|
||||||
|
jumpLink: this.form.jumpLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commentUpdate(param).then((res) => {
|
commentUpdate(param).then((res) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user