refactor(ui): 替换iView为TDesign组件库并优化相关代码

feat(coupon): 新增优惠券详情页面
feat(api): 添加会员评价状态更新和删除接口
perf(pagination): 统一分页大小选项为[20, 50, 100]
style(theme): 移除旧主题文件并更新样式类名
fix(menu): 修复菜单组件兼容性问题
chore(deps): 更新package.json依赖项
docs(modal): 添加全局Modal组件兼容层
This commit is contained in:
pikachu1995@126.com
2025-12-07 19:08:03 +08:00
parent d701c72928
commit 43f214b40a
89 changed files with 2253 additions and 1556 deletions

View File

@@ -72,9 +72,10 @@ Vue.component('t-icon', TIcon)
Vue.component('Page', TdPage)
Vue.prototype.$Message = MessagePlugin
let __lastDialog = null
Vue.prototype.$Modal = {
confirm: function (opts) {
return DialogPlugin.confirm({
const d = DialogPlugin.confirm({
header: opts && (opts.title || opts.header),
content: opts && (opts.content || opts.desc),
theme: opts && opts.theme ? opts.theme : 'default',
@@ -82,38 +83,56 @@ Vue.prototype.$Modal = {
onCancel: opts && opts.onCancel,
onClose: opts && opts.onClose
})
__lastDialog = d
return d
},
info: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '提示'),
content: opts && (opts.content || opts.desc),
theme: 'info',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
success: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '成功'),
content: opts && (opts.content || opts.desc),
theme: 'success',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
warning: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '警告'),
content: opts && (opts.content || opts.desc),
theme: 'warning',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
error: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '错误'),
content: opts && (opts.content || opts.desc),
theme: 'danger',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
remove: function () {
if (__lastDialog && typeof __lastDialog.hide === 'function') {
__lastDialog.hide()
} else if (__lastDialog && typeof __lastDialog.destroy === 'function') {
__lastDialog.destroy()
}
__lastDialog = null
}
}
Vue.prototype.$Notice = {

View File

@@ -15,18 +15,19 @@
"dependencies": {
"@amap/amap-jsapi-loader": "0.0.7",
"@antv/g2": "^4.1.14",
"atob": "^2.1.2",
"axios": "^0.21.1",
"dplayer": "^1.27.1",
"js-cookie": "^2.2.1",
"sass": "^1.63.6",
"price-color": "^1.0.2",
"s": "^1.0.0",
"sass": "^1.63.6",
"sass-loader": "^10.4.1",
"sockjs-client": "^1.4.0",
"swiper": "^5.4.5",
"tdesign-icons-vue": "^0.4.1",
"tdesign-vue": "^1.14.2",
"uuid": "^8.3.2",
"view-design": "^4.6.1",
"atob": "^2.1.2",
"vue": "2.6.14",
"vue-awesome-swiper": "^4.1.1",
"vue-json-excel": "^0.3.0",
@@ -36,7 +37,6 @@
"vue-router": "^3.1.3",
"vuedraggable": "^2.23.2",
"vuex": "^3.4.0",
"tdesign-vue": "^1.14.2",
"xss": "^1.0.7"
},
"devDependencies": {
@@ -51,7 +51,6 @@
"style-loader": "^2.0.0",
"style-resources-loader": "^1.3.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"view-design": "^4.6.1",
"vue-cli-plugin-style-resources-loader": "^0.1.4",
"vue-template-compiler": "2.6.14"
},

View File

@@ -3,9 +3,9 @@ var BASE = {
* @description api请求基础路径
*/
API_DEV: {
common: "http://127.0.0.1:8890",
common: "https://common-api.pickmall.cn",
buyer: "https://buyer-api.pickmall.cn",
seller: "http://127.0.0.1:8889",
seller: "https://store-api.pickmall.cn",
manager: "https://admin-api.pickmall.cn",
},
API_PROD: {

View File

@@ -33,11 +33,11 @@ body {
margin-right: 5px;
}
.ivu-btn-text:focus {
.t-button[variant="text"]:focus {
box-shadow: none !important;
}
.ivu-tag {
.t-tag {
cursor: pointer;
}
.tox-notifications-container{

View File

@@ -16,6 +16,16 @@ export const replyMemberReview = (id, params) => {
return putRequest(`/member/evaluation/reply/${id}`, params);
};
// 修改评价状态
export const updateMemberReview = (id, params) => {
return getRequest(`/member/evaluation/updateStatus/${id}`, params);
};
// 删除评论
export const delMemberReview = (id) => {
return putRequest(`/member/evaluation/delete/${id}`);
};
// 获取会员注册统计列表
export const getStatisticsList = (params) => {
return getRequest("/statistics/view/list", params);

View File

@@ -1,10 +1,11 @@
import axios from "axios";
import { getStore, setStore } from "./storage";
import { router } from "../router/index";
import { Message } from "view-design";
import { MessagePlugin } from 'tdesign-vue';
import Cookies from "js-cookie";
import { handleRefreshToken } from "@/api/index";
import {v4 as uuidv4} from 'uuid';
const Message = MessagePlugin;
// 统一请求路径前缀
export const baseUrl =

View File

@@ -360,10 +360,13 @@ util.initRouter = function (vm) { // 初始化路由
// 缓存数据 修改加载标识
window.localStorage.setItem('menuData', JSON.stringify(menuData));
vm.$store.commit('setAdded', true);
if(vm.$store.state.app.refMenu){
vm.$nextTick(()=>{
vm.$store.state.app.refMenu.updateActiveName();
});
if (vm.$store.state.app.refMenu) {
vm.$nextTick(() => {
const menu = vm.$store.state.app.refMenu
if (menu && typeof menu.updateActiveName === 'function') {
menu.updateActiveName()
}
})
}
})

View File

@@ -1,6 +1,4 @@
import Vue from "vue";
import ViewUI from "view-design";
import "./styles/theme.less";
import TDesign from 'tdesign-vue'
import 'tdesign-vue/es/style/index.css'
import { Icon as TIcon } from 'tdesign-icons-vue'
@@ -57,14 +55,12 @@ Vue.use(priceColorScheme);
Vue.use(TDesign)
Vue.component('t-icon', TIcon)
const copyViewUi = {...ViewUI}
copyViewUi.Input.props.maxlength.default = inputMaxLength // 挂载最大输入值
Vue.use(copyViewUi);
Vue.prototype.$Message = MessagePlugin
let __lastDialog = null
Vue.prototype.$Modal = {
confirm: function (opts) {
return DialogPlugin.confirm({
const d = DialogPlugin.confirm({
header: opts && (opts.title || opts.header),
content: opts && (opts.content || opts.desc),
theme: opts && opts.theme ? opts.theme : 'default',
@@ -72,38 +68,56 @@ Vue.prototype.$Modal = {
onCancel: opts && opts.onCancel,
onClose: opts && opts.onClose
})
__lastDialog = d
return d
},
info: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '提示'),
content: opts && (opts.content || opts.desc),
theme: 'info',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
success: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '成功'),
content: opts && (opts.content || opts.desc),
theme: 'success',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
warning: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '警告'),
content: opts && (opts.content || opts.desc),
theme: 'warning',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
error: function (opts) {
return DialogPlugin.alert({
const d = DialogPlugin.alert({
header: opts && (opts.title || '错误'),
content: opts && (opts.content || opts.desc),
theme: 'danger',
onClose: opts && (opts.onOk || opts.onClose)
})
__lastDialog = d
return d
},
remove: function () {
if (__lastDialog && typeof __lastDialog.hide === 'function') {
__lastDialog.hide()
} else if (__lastDialog && typeof __lastDialog.destroy === 'function') {
__lastDialog.destroy()
}
__lastDialog = null
}
}
Vue.prototype.$Notice = {
@@ -137,15 +151,82 @@ Vue.prototype.$Notice = {
}
Vue.component('Input', {
inheritAttrs: false,
props: ['value','type'],
model: { prop: 'value', event: 'input' },
render(h){
const rawAttrs = this.$attrs || {}
const inputType = this.type || rawAttrs.type || 'text'
const baseProps = Object.assign({}, rawAttrs, { value: this.value })
delete baseProps.type
const on = Object.assign({}, this.$listeners, {
enter: e => this.$emit('on-enter', e),
clear: e => this.$emit('on-clear', e),
input: v => this.$emit('input', v),
change: v => this.$emit('input', v)
})
if (String(inputType).toLowerCase() === 'textarea') {
return h('t-textarea', { props: baseProps, on })
}
const props = Object.assign({}, baseProps)
if (String(inputType).toLowerCase() === 'password') props.type = 'password'
const inputNode = h('t-input', { props, on })
const prepend = this.$slots.prepend
const append = this.$slots.append
if (prepend || append) {
const children = []
if (prepend) children.push(h('div', { slot: 'prepend' }, prepend))
children.push(inputNode)
if (append) children.push(h('div', { slot: 'append' }, append))
return h('t-input-adornment', {}, children)
}
return inputNode
}
})
Vue.component('i-input', {
inheritAttrs: false,
props: ['value','type'],
model: { prop: 'value', event: 'input' },
render(h){
const rawAttrs = this.$attrs || {}
const inputType = this.type || rawAttrs.type || 'text'
const baseProps = Object.assign({}, rawAttrs, { value: this.value })
delete baseProps.type
const on = Object.assign({}, this.$listeners, {
enter: e => this.$emit('on-enter', e),
clear: e => this.$emit('on-clear', e),
input: v => this.$emit('input', v),
change: v => this.$emit('input', v)
})
if (String(inputType).toLowerCase() === 'textarea') {
return h('t-textarea', { props: baseProps, on })
}
const props = Object.assign({}, baseProps)
if (String(inputType).toLowerCase() === 'password') props.type = 'password'
const inputNode = h('t-input', { props, on })
const prepend = this.$slots.prepend
const append = this.$slots.append
if (prepend || append) {
const children = []
if (prepend) children.push(h('div', { slot: 'prepend' }, prepend))
children.push(inputNode)
if (append) children.push(h('div', { slot: 'append' }, append))
return h('t-input-adornment', {}, children)
}
return inputNode
}
})
Vue.component('AutoComplete', {
inheritAttrs: false,
props: ['value'],
model: { prop: 'value', event: 'input' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value })
const on = Object.assign({}, this.$listeners, {
enter: e => this.$emit('on-enter', e),
clear: e => this.$emit('on-clear', e),
input: v => this.$emit('input', v)
focus: e => this.$emit('on-focus', e),
blur: e => this.$emit('on-blur', e),
input: v => this.$emit('input', v),
change: v => this.$emit('on-change', v)
})
return h('t-input', { props, on })
}
@@ -154,10 +235,40 @@ Vue.component('Button', {
inheritAttrs: false,
render(h){
const attrs = this.$attrs || {}
const theme = attrs.theme || (attrs.type === 'primary' ? 'primary' : attrs.type)
const props = Object.assign({}, attrs, { theme })
const type = attrs.type
const typeToTheme = {
primary: 'primary',
success: 'success',
warning: 'warning',
error: 'danger',
danger: 'danger',
default: 'default',
info: 'default'
}
const typeToVariant = {
dashed: 'dashed',
text: 'text',
link: 'text',
ghost: 'outline',
outline: 'outline'
}
const theme = attrs.theme || typeToTheme[type]
const variant = attrs.variant || typeToVariant[type]
const props = Object.assign({}, attrs, { theme, variant })
if (attrs.long) {
props.block = true
delete props.long
}
delete props.type
return h('t-button', { props, on: this.$listeners }, this.$slots.default)
let data = { props, on: this.$listeners }
if (attrs.icon && typeof attrs.icon === 'string') {
const iconName = attrs.icon
delete props.icon
data.scopedSlots = {
icon: () => h('Icon', { props: { type: iconName, size: '16' } })
}
}
return h('t-button', data, this.$slots.default)
}
})
Vue.component('Spin', {
@@ -168,21 +279,53 @@ Vue.component('Spin', {
}
})
Vue.component('Page', {
props: ['total','current','pageSize','showTotal','showElevator','size'],
props: ['total','current','pageSize','showTotal','showElevator','size','pageSizeOpts','showSizer'],
render(h){
const showJumper = !!(this.showElevator || this.showTotal)
const pageSizeOptions = this.pageSizeOpts || this.$attrs['page-size-opts'] || [10, 20, 50]
const showPageSize = !!(this.showSizer || this.$attrs['show-sizer'])
return h('t-pagination', {
props: { total: Number(this.total) || 0, current: this.current || 1, pageSize: this.pageSize || 10, showJumper, size: this.size === 'small' ? 'small' : 'medium' },
on: { change: ({ current }) => this.$emit('on-change', current) }
props: {
total: Number(this.total) || 0,
current: this.current || 1,
pageSize: this.pageSize || 10,
showJumper,
size: this.size === 'small' ? 'small' : 'medium',
pageSizeOptions,
showPageSize
},
on: {
change: ({ current, pageSize }) => {
this.$emit('on-change', current)
this.$emit('change', { current, pageSize })
},
'page-size-change': (size) => {
this.$emit('on-page-size-change', size)
}
}
})
}
})
Vue.component('Tag', {
props: ['color'],
render(h){
let theme = 'default'
if(this.color === 'geekblue') theme = 'primary'
return h('t-tag', { props: { theme } }, this.$slots.default)
const map = {
blue: 'primary',
geekblue: 'primary',
cyan: 'primary',
green: 'success',
success: 'success',
red: 'danger',
magenta: 'danger',
volcano: 'warning',
orange: 'warning',
warning: 'warning',
pink: 'default',
purple: 'default',
default: 'default'
}
const theme = map[this.color] || 'default'
return h('t-tag', { props: { theme, variant: 'light', size: 'small' } }, this.$slots.default)
}
})
Vue.component('Cascader', {
@@ -195,13 +338,162 @@ Vue.component('Cascader', {
return h('t-cascader', { props, on })
}
})
Vue.component('DatePicker', {
inheritAttrs: false,
props: ['value','type','format','clearable','placeholder'],
model: { prop: 'value', event: 'input' },
render(h){
const type = this.type || this.$attrs.type || 'date'
const hasTime = /time/gi.test(type)
const isRange = /range/gi.test(type)
const fmt = this.format || this.$attrs.format || (hasTime ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd')
const fmtUpper = fmt.replace(/y/g,'Y').replace(/d/g,'D')
const options = this.$attrs.options || this.$attrs['options'] || {}
const props = Object.assign({}, this.$attrs, {
clearable: this.clearable !== false,
format: fmtUpper,
enableTimePicker: hasTime,
valueType: 'time-stamp',
placeholder: this.placeholder || this.$attrs.placeholder
})
props.value = isRange ? (Array.isArray(this.value) ? this.value : []) : this.value
if (options && typeof options.disabledDate === 'function') {
props.disableDate = options.disabledDate
}
const on = Object.assign({}, this.$listeners, {
change: v => { this.$emit('input', v); this.$emit('on-change', v) }
})
return isRange ? h('t-date-range-picker', { props, on }) : h('t-date-picker', { props, on })
}
})
Vue.component('Date-picker', {
inheritAttrs: false,
functional: true,
render(h, ctx){
const data = ctx.data || {}
const props = data.props || {}
const type = props.type || data.attrs && data.attrs.type || 'date'
const hasTime = /time/gi.test(type)
const isRange = /range/gi.test(type)
const fmt = props.format || (data.attrs && data.attrs.format) || (hasTime ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd')
const fmtUpper = fmt.replace(/y/g,'Y').replace(/d/g,'D')
const p = Object.assign({}, data.attrs, props, { format: fmtUpper, enableTimePicker: hasTime, valueType: 'time-stamp' })
p.value = isRange ? (Array.isArray(p.value) ? p.value : []) : p.value
const on = Object.assign({}, data.on, { change: v => { ctx.listeners && ctx.listeners.input && ctx.listeners.input(v); ctx.listeners && ctx.listeners['on-change'] && ctx.listeners['on-change'](v) } })
return isRange ? h('t-date-range-picker', { props: p, on }, ctx.children) : h('t-date-picker', { props: p, on }, ctx.children)
}
})
Vue.component('Form', {
inheritAttrs: false,
props: ['model','rules','inline','labelWidth'],
render(h){
const data = this.model || this.$attrs.model
const rules = this.rules || this.$attrs.rules
const labelWidth = this.labelWidth || this.$attrs.labelWidth
const layout = this.inline ? 'inline' : 'vertical'
const props = Object.assign({}, this.$attrs, { data, rules, labelWidth, layout })
const on = Object.assign({}, this.$listeners)
return h('t-form', { ref: 'formInner', props, on }, this.$slots.default)
},
methods: {
validate(cb, fields){
const inner = this.$refs.formInner
if (!inner) return
const res = inner.validate(fields)
if (res && typeof res.then === 'function') {
res.then(result => { if (typeof cb === 'function') cb(result === true) })
} else {
if (typeof cb === 'function') cb(res === true || res)
}
},
reset(){
this.$refs.formInner && this.$refs.formInner.reset()
},
resetFields(){
this.reset()
}
}
})
Vue.component('RadioGroup', {
inheritAttrs: false,
props: ['value'],
model: { prop: 'value', event: 'change' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('input', v); this.$emit('on-change', v); this.$emit('change', v) } })
return h('t-radio-group', { props, on }, this.$slots.default)
}
})
Vue.component('Radio', {
inheritAttrs: false,
props: ['label','value'],
render(h){
const value = typeof this.value !== 'undefined' ? this.value : this.label
const on = Object.assign({}, this.$listeners, { change: e => { this.$emit('on-change', e); this.$emit('change', e) }, click: e => { this.$emit('on-change', e); this.$emit('change', e) } })
return h('t-radio', { props: { value }, on }, this.$slots.default)
}
})
Vue.component('CheckboxGroup', {
inheritAttrs: false,
props: ['value'],
model: { prop: 'value', event: 'input' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('input', v); this.$emit('on-change', v) } })
return h('t-checkbox-group', { props, on }, this.$slots.default)
}
})
Vue.component('Checkbox', {
inheritAttrs: false,
props: ['label','value','trueValue','falseValue'],
render(h){
const val = typeof this.value !== 'undefined' ? this.value : this.label
return h('t-checkbox', { props: Object.assign({}, this.$attrs, { value: val }) }, this.$slots.default)
}
})
Vue.component('InputNumber', {
inheritAttrs: false,
props: ['value','min','max','step','size'],
model: { prop: 'value', event: 'input' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value, min: this.min, max: this.max, step: this.step })
const on = Object.assign({}, this.$listeners, { change: v => this.$emit('input', v) })
const inputNode = h('t-input-number', { props, on })
const append = this.$slots.append
if (append) {
return h('t-input-adornment', {}, [
inputNode,
h('div', { slot: 'append' }, append)
])
}
return inputNode
}
})
Vue.component('FormItem', {
inheritAttrs: false,
props: ['label','prop','name','labelWidth'],
render(h){
const name = this.name || this.prop || this.$attrs.prop
const props = Object.assign({}, this.$attrs, { label: this.label, name, labelWidth: this.labelWidth || this.$attrs.labelWidth })
return h('t-form-item', { props }, this.$slots.default)
}
})
Vue.component('Form-item', {
inheritAttrs: false,
props: ['label','prop','name','labelWidth'],
render(h){
const name = this.name || this.prop || this.$attrs.prop
const props = Object.assign({}, this.$attrs, { label: this.label, name, labelWidth: this.labelWidth || this.$attrs.labelWidth })
return h('t-form-item', { props }, this.$slots.default)
}
})
Vue.component('Tabs', {
inheritAttrs: false,
props: ['value'],
model: { prop: 'value', event: 'change' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value })
const on = Object.assign({}, this.$listeners, { change: v => this.$emit('change', v) })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('change', v); this.$emit('on-click', v) } })
return h('t-tabs', { props, on }, this.$slots.default)
}
})
@@ -227,28 +519,58 @@ Vue.component('Col', {
return h('t-col', { props }, this.$slots.default)
}
})
Vue.component('Menu', {
inheritAttrs: false,
props: ['activeName','theme','width'],
render(h){
const value = this.activeName || this.$attrs['active-name']
const props = Object.assign({}, this.$attrs, { value, theme: this.theme || this.$attrs.theme, width: this.width || this.$attrs.width })
const on = Object.assign({}, this.$listeners, { change: v => this.$emit('on-select', v) })
return h('t-menu', { props, on }, this.$slots.default)
}
})
Vue.component('MenuItem', {
inheritAttrs: false,
props: ['name','value'],
render(h){
const value = typeof this.value !== 'undefined' ? this.value : this.name || this.$attrs.name
return h('t-menu-item', { props: Object.assign({}, this.$attrs, { value }) }, this.$slots.default)
}
})
Vue.component('MenuGroup', {
inheritAttrs: false,
props: ['title','name'],
render(h){
const title = this.title || this.$attrs.title
const children = []
if (title) children.push(h('span', { slot: 'title' }, [title]))
if (this.$slots.default) children.push(...this.$slots.default)
return h('t-submenu', { props: { value: this.name || title } }, children)
}
})
Vue.component('Modal', {
inheritAttrs: false,
props: ['value','title','footerHide','closable','maskClosable'],
model: { prop: 'value', event: 'input' },
render(h){
const props = {
const props = Object.assign({}, this.$attrs, {
visible: !!this.value,
header: this.title,
closeOnOverlayClick: this.maskClosable !== false,
closeBtn: this.closable !== false,
}
closeBtn: this.closable !== false
})
const on = {
confirm: e => this.$emit('on-ok', e),
cancel: e => this.$emit('on-cancel', e),
close: e => this.$emit('on-close', e),
'update:visible': v => this.$emit('input', v)
}
const slots = Object.assign({}, this.$slots)
if(this.footerHide){
props.footer = null
}
return h('t-dialog', { props, on }, slots.default)
const children = []
if (this.$slots.header) children.push(h('div', { slot: 'header' }, this.$slots.header))
if (this.footerHide) props.footer = null
if (this.$slots.footer && !this.footerHide) children.push(h('div', { slot: 'footer' }, this.$slots.footer))
if (this.$slots.default) children.push(...this.$slots.default)
return h('t-dialog', { props, on }, children)
}
})
Vue.component('Drawer', {
@@ -256,10 +578,12 @@ Vue.component('Drawer', {
props: ['value','title','size','closeOnOverlayClick'],
model: { prop: 'value', event: 'input' },
render(h){
let sizeVal = this.size || this.$attrs.size
if (typeof sizeVal === 'number') sizeVal = `${sizeVal}px`
const props = {
visible: !!this.value,
header: this.title,
size: this.size || 400,
size: sizeVal,
closeOnOverlayClick: this.closeOnOverlayClick !== false
}
const on = {
@@ -268,6 +592,17 @@ Vue.component('Drawer', {
return h('t-drawer', { props, on }, this.$slots.default)
}
})
Vue.component('Card', {
inheritAttrs: false,
render(h){
const dataNode = (this.$vnode && this.$vnode.data) || {}
const props = Object.assign({}, this.$attrs)
const data = { props }
if (dataNode.class) data.class = dataNode.class
if (dataNode.style) data.style = dataNode.style
return h('t-card', data, this.$slots.default)
}
})
Vue.component('Alert', {
props: ['type','title'],
render(h){
@@ -275,6 +610,14 @@ Vue.component('Alert', {
return h('t-alert', { props: { theme, message: this.title } })
}
})
Vue.component('Badge', {
props: ['status','text'],
render(h){
const map = { success: 'success', error: 'danger', warning: 'warning', processing: 'primary', default: 'default' }
const theme = map[this.status] || 'default'
return h('t-tag', { props: { theme, size: 'small', variant: 'light' } }, this.text || (this.$slots.default && this.$slots.default[0]))
}
})
Vue.component('Table', {
props: ['columns','data','loading','height','border','rowKey','tooltip'],
render(h){
@@ -288,10 +631,25 @@ Vue.component('Table', {
nc.colKey = c.key
delete nc.key
}
if(c.slot && !nc.colKey){
nc.colKey = c.slot
delete nc.slot
}
if(c.type === 'selection' && !nc.colKey){
nc.colKey = 'row-select'
nc.type = 'multiple'
}
return nc
})
const props = { columns: cols, data: this.data, loading: this.loading, height: this.height, rowKey: this.rowKey || 'id' }
return h('t-table', { props })
const on = Object.assign({}, this.$listeners, {
'select-change': (keys, context) => {
this.$emit('on-selection-change', context.selectedRowData)
this.$emit('select-change', keys, context)
},
'sort-change': e => this.$emit('on-sort-change', e)
})
return h('t-table', { props, on })
}
})
Vue.component('Select', {
@@ -327,7 +685,9 @@ Vue.component('Poptip', {
inheritAttrs: false,
props: ['title','placement'],
render(h){
const props = { content: this.title || this.$attrs.content, placement: this.placement || 'top' }
const props = { content: this.title || this.$attrs.content, placement: this.placement || 'top', trigger: this.$attrs.trigger || 'hover' }
const width = this.$attrs.width || this.$attrs['max-width']
if (width) props.overlayStyle = { width: typeof width === 'number' ? `${width}px` : width }
const on = Object.assign({}, this.$listeners, { confirm: e => this.$emit('on-ok', e), cancel: e => this.$emit('on-cancel', e) })
return h('t-popconfirm', { props, on }, this.$slots.default)
}
@@ -341,9 +701,37 @@ Vue.component('Icon', {
'md-heart': 'heart',
'md-document': 'file',
'md-person': 'user',
'ios-person': 'user',
'ios-link': 'link',
'ios-videocam': 'video',
'md-share-alt': 'share'
'md-share-alt': 'share',
'md-cloud-download': 'download',
'md-trash': 'delete',
'ios-trash-outline': 'delete',
'ios-eye': 'view',
'ios-eye-outline': 'view',
'ios-search': 'search',
'md-search': 'search',
'ios-information-circle-outline': 'info-circle',
'md-checkmark': 'check',
'edit': 'edit',
'ios-cloud-upload': 'upload',
'md-refresh': 'refresh',
'md-arrow-round-forward': 'arrow-right',
'md-eye': 'view',
'ios-arrow-back': 'arrow-left',
'android-time': 'time',
'md-notifications': 'notification',
'android-lock': 'lock',
'ios-navigate-outline': 'navigate',
'social-freebsd-devil': 'error',
'key': 'key',
'md-phone-portrait': 'phone',
'md-lock': 'lock',
'md-list': 'list',
'md-list-box': 'list',
'md-arrow-dropdown': 'chevron-down',
'md-chatbubbles': 'chat'
}
const name = map[this.type] || this.type || 'link'
const props = { name: name, size: this.size }
@@ -352,6 +740,272 @@ Vue.component('Icon', {
return h('t-icon', { props, ...data })
}
})
Vue.component('Divider', {
inheritAttrs: false,
render(h){
return h('t-divider', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Dropdown', {
inheritAttrs: false,
render(h){
const on = Object.assign({}, this.$listeners, {
click: v => { this.$emit('on-click', v); this.$emit('click', v) }
})
return h('t-dropdown', { props: this.$attrs, on }, this.$slots.default)
}
})
Vue.component('DropdownMenu', {
inheritAttrs: false,
render(h){
return h('t-dropdown-menu', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('DropdownItem', {
inheritAttrs: false,
props: ['name','value','label'],
render(h){
const value = typeof this.value !== 'undefined' ? this.value : this.name
const contentSlot = this.$slots.default && this.$slots.default[0] && this.$slots.default[0].text
const content = this.label || contentSlot
const props = Object.assign({}, this.$attrs, { value, content })
return h('t-dropdown-item', { props })
}
})
Vue.component('Breadcrumb', {
inheritAttrs: false,
render(h){
return h('t-breadcrumb', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('BreadcrumbItem', {
inheritAttrs: false,
props: ['to','replace'],
render(h){
const props = Object.assign({}, this.$attrs, { to: this.to || this.$attrs.to, replace: this.replace || this.$attrs.replace })
return h('t-breadcrumb-item', { props }, this.$slots.default)
}
})
Vue.component('Upload', {
inheritAttrs: false,
props: ['action','data','headers','maxSize','showUploadList','multiple'],
render(h){
const props = Object.assign({}, this.$attrs, {
action: this.action || this.$attrs.action,
data: this.data || this.$attrs.data,
headers: this.headers || this.$attrs.headers,
multiple: this.multiple || this.$attrs.multiple,
showUploadFileList: this.showUploadList !== false,
sizeLimit: this.maxSize || this.$attrs.maxSize
})
const format = this.$attrs.format
if (Array.isArray(format)) {
const accept = format.map(ext => {
const e = String(ext || '').trim()
return e.startsWith('.') ? e : `.${e}`
}).join(',')
props.accept = accept
delete props.format
}
const on = Object.assign({}, this.$listeners, {
fail: e => { this.$emit('on-error', e); this.$emit('fail', e) },
success: ctx => { this.$emit('on-success', ctx); this.$emit('success', ctx) },
progress: e => { this.$emit('on-progress', e) }
})
return h('t-upload', { props, on }, this.$slots.default)
}
})
Vue.component('Steps', {
inheritAttrs: false,
props: ['current','status'],
render(h){
const props = Object.assign({}, this.$attrs, { current: this.current })
const on = Object.assign({}, this.$listeners, { change: v => this.$emit('on-change', v) })
return h('t-steps', { props, on }, this.$slots.default)
}
})
Vue.component('Step', {
inheritAttrs: false,
props: ['title','content','icon'],
render(h){
const icon = this.icon || this.$attrs.icon
const props = { title: this.title || this.$attrs.title, content: this.content || this.$attrs.content }
const data = { props }
if (icon && typeof icon === 'string') {
data.scopedSlots = {
icon: () => h('Icon', { props: { type: icon, size: '16' } })
}
}
return h('t-step-item', data, this.$slots.default)
}
})
Vue.component('Collapse', {
inheritAttrs: false,
props: ['value','accordion'],
model: { prop: 'value', event: 'change' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value, expandMutex: !!this.accordion })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('input', v); this.$emit('on-change', v) } })
return h('t-collapse', { props, on }, this.$slots.default)
}
})
Vue.component('Panel', {
inheritAttrs: false,
props: ['name','title'],
render(h){
const value = this.name || this.$attrs.name
const header = this.title || this.$attrs.title
const children = []
if (header) children.push(h('div', { slot: 'header' }, [header]))
if (this.$slots.default) children.push(...this.$slots.default)
return h('t-collapse-panel', { props: { value } }, children)
}
})
Vue.component('Timeline', {
inheritAttrs: false,
render(h){
return h('t-timeline', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('TimelineItem', {
inheritAttrs: false,
props: ['color','dot','label'],
render(h){
const props = Object.assign({}, this.$attrs, { label: this.label || this.$attrs.label })
return h('t-timeline-item', { props }, this.$slots.default)
}
})
Vue.component('Progress', {
inheritAttrs: false,
props: ['percent','status','strokeWidth','type'],
render(h){
const percentage = typeof this.percent !== 'undefined' ? this.percent : this.$attrs.percent
const props = Object.assign({}, this.$attrs, { percentage, strokeWidth: this.strokeWidth || this.$attrs['stroke-width'] })
return h('t-progress', { props })
}
})
Vue.component('i-circle', {
inheritAttrs: false,
props: ['size','strokeColor','trailWidth','strokeWidth','percent','strokeLinecap'],
render(h){
let sizeVal = this.size || this.$attrs.size
const percentage = Number(this.percent || this.$attrs.percent) || 0
const props = {
theme: 'circle',
percentage,
size: sizeVal,
color: this.strokeColor || this.$attrs['stroke-color'],
trackColor: this.$attrs['trail-color'] || '',
strokeWidth: this.strokeWidth || this.$attrs['stroke-width']
}
const data = { props }
if (this.$slots.default) {
data.scopedSlots = { label: () => this.$slots.default }
}
return h('t-progress', data)
}
})
Vue.component('Slider', {
inheritAttrs: false,
props: ['value','min','max','step','range','disabled'],
model: { prop: 'value', event: 'input' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value, min: this.min, max: this.max, step: this.step, range: !!this.range, disabled: this.disabled })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('input', v); this.$emit('on-change', v) } })
return h('t-slider', { props, on })
}
})
Vue.component('Rate', {
inheritAttrs: false,
props: ['value','allowHalf','count','disabled'],
model: { prop: 'value', event: 'change' },
render(h){
const props = Object.assign({}, this.$attrs, { value: this.value, count: this.count || this.$attrs.count, allowHalf: !!(this.allowHalf || this.$attrs['allow-half']), disabled: this.disabled })
const on = Object.assign({}, this.$listeners, { change: v => { this.$emit('input', v); this.$emit('on-change', v); this.$emit('change', v) } })
return h('t-rate', { props, on })
}
})
Vue.component('t-button-group', {
inheritAttrs: false,
render(h){
const data = { attrs: this.$attrs, class: 't-button-group' }
return h('div', data, this.$slots.default)
}
})
Vue.component('ButtonGroup', {
inheritAttrs: false,
render(h){
const data = { attrs: this.$attrs, class: 't-button-group' }
return h('div', data, this.$slots.default)
}
})
Vue.component('Layout', {
inheritAttrs: false,
render(h){
return h('t-layout', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Header', {
inheritAttrs: false,
render(h){
return h('t-header', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Sider', {
inheritAttrs: false,
render(h){
return h('t-aside', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Content', {
inheritAttrs: false,
render(h){
return h('t-content', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Footer', {
inheritAttrs: false,
render(h){
return h('t-footer', { props: this.$attrs }, this.$slots.default)
}
})
Vue.component('Submenu', {
inheritAttrs: false,
props: ['name','title'],
render(h){
const title = this.title || this.$attrs.title
const children = []
if (title) children.push(h('span', { slot: 'title' }, [title]))
if (this.$slots.default) children.push(...this.$slots.default)
const value = this.name || title
return h('t-submenu', { props: { value } }, children)
}
})
Vue.component('Avatar', {
inheritAttrs: false,
props: ['src','size','shape'],
render(h){
const props = Object.assign({}, this.$attrs, { image: this.src || this.$attrs.src, size: this.size || this.$attrs.size, shape: this.shape || this.$attrs.shape })
const data = { props }
const icon = this.$attrs.icon
if (icon && typeof icon === 'string') {
delete props.icon
data.scopedSlots = {
icon: () => h('Icon', { props: { type: icon } })
}
}
return h('t-avatar', data, this.$slots.default)
}
})
Vue.component('Scroll', {
inheritAttrs: false,
render(h){
const styleNode = (this.$vnode && this.$vnode.data && this.$vnode.data.style) || {}
const style = Object.assign({}, styleNode, { overflow: 'auto' })
return h('div', { style }, this.$slots.default)
}
})
Vue.component('liliDialog', liliDialog)
@@ -419,3 +1073,69 @@ new Vue({
this.$store.commit("initCachepage");
}
});
Vue.component('ColorPicker', {
inheritAttrs: false,
props: ['value'],
model: { prop: 'value', event: 'input' },
render(h){
const on = Object.assign({}, this.$listeners, { change: v => this.$emit('input', v) })
const props = Object.assign({}, this.$attrs, { value: this.value })
return h('t-color-picker', { props, on })
}
})
Vue.component('Tree', {
inheritAttrs: false,
props: ['data'],
methods: {
getCheckedAndIndeterminateNodes(){
const res = []
const walk = (arr) => {
(arr || []).forEach(n => {
if (n.checked || n.indeterminate || n.halfChecked) res.push(n)
if (n.children && n.children.length) walk(n.children)
})
}
const list = this.data || this.$attrs.data || []
walk(list)
return res
}
},
render(h){
const toTreeData = (list) => {
if (!Array.isArray(list)) return []
return list.map(n => {
const node = {
label: n.title || n.label,
value: n.id || n.value,
disabled: !!n.disabled,
expanded: !!n.expand,
origin: n
}
if (Array.isArray(n.children) && n.children.length) node.children = toTreeData(n.children)
return node
})
}
const props = Object.assign({}, this.$attrs, { data: toTreeData(this.data || this.$attrs.data) })
if (this.$attrs.showCheckbox) props.checkable = true
props.activable = true
const on = Object.assign({}, this.$listeners, {
active: (ctx) => {
const node = ctx && ctx.node && ctx.node.data && ctx.node.data.origin
this.$emit('on-select-change', node ? [node] : [])
},
change: (val, ctx) => {
const node = ctx && ctx.node && ctx.node.data && ctx.node.data.origin
this.$emit('on-check-change', node ? [node] : [])
}
})
const data = {}
const renderFn = this.$attrs.render
if (renderFn) {
data.scopedSlots = {
label: (ctx) => renderFn(h, ctx)
}
}
return h('t-tree', { props, on, ...data })
}
})

View File

@@ -1,5 +1,4 @@
import Vue from 'vue';
import ViewUI from 'view-design';
import Util from '../libs/util';
import VueRouter from 'vue-router';
import Cookies from 'js-cookie';
@@ -24,7 +23,6 @@ VueRouter.prototype.push = function push(location) {
export const router = new VueRouter(RouterConfig);
router.beforeEach((to, from, next) => {
ViewUI.LoadingBar.start();
Util.title(to.meta.title);
next();
@@ -54,6 +52,5 @@ router.beforeEach((to, from, next) => {
router.afterEach((to) => {
Util.openNewPage(router.app, to.name, to.params, to.query);
ViewUI.LoadingBar.finish();
window.scrollTo(0, 0);
});

View File

@@ -71,6 +71,12 @@ export const otherRouter = {
name: "add-coupon",
component: () => import("@/views/promotion/coupon/coupon-publish.vue")
},
{
path: "coupon-info",
title: "优惠券详情",
name: "coupon-info",
component: () => import("@/views/promotion/coupon/coupon-info.vue")
},
{
path: "add-live",
title: "创建直播",

View File

@@ -19,7 +19,7 @@
// background-color: #f0f0f0;
border-radius: 0.4em;
flex-wrap: wrap;
> .ivu-form-item {
> .t-form__item {
margin: 8px 10px !important;
}
}
@@ -38,7 +38,7 @@
overflow: hidden;
}
// 为Card组件之间增加间距
.ivu-card + .ivu-card {
// 为Card组件之间增加间距TDesign
.t-card + .t-card {
margin-top: 10px;
}

View File

@@ -1,12 +0,0 @@
@import "~view-design/src/styles/index.less";
// iview 自定义样式
@primary-color: #F31947;
@info-color: #fa6419;
@success-color: #68cabe;
@error-color: #ff3c2a;
@table-thead-bg: #f8f8f9;
@table-td-stripe-bg: #f8f8f9;
@table-td-hover-bg: #ededed;
@table-td-highlight-bg: #ededed;
@font-size-base: 12px;

View File

@@ -292,7 +292,7 @@ export default {
.other-login {
margin: 0 auto;
.ivu-icon {
.t-icon {
font-size: 24px;
}
}

View File

@@ -1,22 +1,21 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="商品名称" prop="goodsName">
<Input type="text" v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable style="width: 240px"/>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
</Form>
</Row>
</Card>
<Card>
<Row class="operation padding-row">
<Button @click="add" type="primary">添加</Button>
</Row>
<Table class="mt_10" :loading="loading" border :columns="columns" :data="data" ref="table" >
<!-- 商品栏目格式化 -->
<template slot="goodsSlot" slot-scope="{row}">
<t-card>
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form">
<t-form-item label="商品名称" name="goodsName">
<t-input v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable style="width: 240px" />
</t-form-item>
<t-form-item>
<t-button @click="handleSearch" theme="primary" class="search-btn">搜索</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="operation padding-row">
<t-button @click="add" theme="primary">添加</t-button>
</div>
<t-table class="mt_10" :loading="loading" :columns="tColumns" :data="data" rowKey="id">
<template #goodsSlot="{ row }">
<div style="margin-top: 5px;height: 70px; display: flex;">
<div style="">
<img :src="row.thumbnail" style="height: 60px;margin-top: 3px;width: 60px">
@@ -26,44 +25,35 @@
<div class="div-zoom">
<a @click="linkTo(row.goodsId,row.skuId)">{{row.goodsName}}</a>
</div>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<t-popup trigger="hover" placement="top">
<template #content>
<vue-qr :text="wapLinkTo(row.goodsId,row.skuId)" :margin="0" colorDark="#000" colorLight="#fff" :size="150"></vue-qr>
</div>
<img src="../../assets/qrcode.svg" class="hover-pointer" width="20" height="20" alt="">
</Poptip>
</div>
</div>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10,20,50]" size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
<img src="../../assets/qrcode.svg" class="hover-pointer" width="20" height="20" alt="">
</t-popup>
</div>
</div>
</template>
</t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" @change="({ current }) => changePage(current)" @page-size-change="(size) => changePageSize(size)" :pageSizeOptions="[20, 50, 100]" size="small" showJumper showPageSize></t-pagination>
</div>
</t-card>
<liliDialog
ref="liliDialog"
@selectedGoodsData="selectedGoodsData"
></liliDialog>
<Modal
:title="modalTitle"
v-model="modalVisible"
:mask-closable="false"
:width="500"
>
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
<FormItem label="分销佣金" prop="commission">
<Input v-model="form.commission" clearable style="width: 100%"/>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
>提交
</Button
>
</div>
</Modal>
<t-dialog :header="modalTitle" :visible="modalVisible" :width="500" :closeOnOverlayClick="false" @close="modalVisible = false">
<t-form ref="form" :data="form" :labelWidth="100" :rules="formValidate">
<t-form-item label="分销佣金" name="commission">
<t-input v-model="form.commission" clearable style="width: 100%" />
</t-form-item>
</t-form>
<template #footer>
<t-button variant="text" @click="modalVisible = false">取消</t-button>
<t-button theme="primary" :loading="submitLoading" @click="handleSubmit">提交</t-button>
</template>
</t-dialog>
</div>
</template>
@@ -90,7 +80,7 @@ export default {
loading: true, // 表单加载状态
searchForm: { // 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
},
@@ -176,6 +166,21 @@ export default {
total: 0 // 表单数据总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
methods: {
init() { // 初始化数据
this.getDataList();
@@ -197,7 +202,6 @@ export default {
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.$refs.table.selectAll(false);
},
// 添加商品
handleSubmit(){
@@ -221,7 +225,7 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取商品列表
@@ -261,7 +265,7 @@ export default {
getShopList (val) {
const params = {
pageNumber:1,
pageSize:10,
pageSize:20,
storeName:''
}
if (val) {

View File

@@ -14,7 +14,7 @@
<Card>
<Table class="mt_10" :loading="loading" border :columns="columns" :data="data" ref="table"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10,20,50]" size="small"
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small"
show-total show-elevator show-sizer></Page>
</Row>
</Card>
@@ -38,7 +38,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort:"create_time",
order:"desc"
},
@@ -126,7 +126,7 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取订单数据

View File

@@ -2,68 +2,63 @@
<div>
<Card>
<div class="operation">
<Button @click="addParent">添加一级分类</Button>
<Button @click="refresh">刷新列表</Button>
<t-button theme="primary" @click="addParent">添加一级分类</t-button>
<t-button @click="refresh">刷新列表</t-button>
</div>
<tree-table
ref="treeTable"
<t-enhanced-table
size="small"
:loading="loading"
:data="tableData"
:columns="columns"
rowKey="id"
:border="true"
:show-index="false"
:is-fold="true"
:expand-type="false"
primary-key="id">
<template slot="action" slot-scope="scope">
<a @click="edit(scope.row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">编辑</a>
:tree="{ childrenKey: 'children', treeNodeColumnIndex: 0, indent: 24, expandTreeNodeOnClick: true }">
<template #action="{ row }">
<a @click="edit(row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">编辑</a>
<span style="margin:0 8px;color:#dcdee2">|</span>
<a v-show="scope.row.level != 1" @click="addChildren(scope.row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">添加子分类</a>
<a v-show="row.level != 1" @click="addChildren(row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">添加子分类</a>
<span style="margin:0 8px;color:#dcdee2">|</span>
<a @click="remove(scope.row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">删除</a>
<a @click="remove(row)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">删除</a>
</template>
</tree-table>
</t-enhanced-table>
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable='false' :width="500">
<Form ref="formAdd" :model="formAdd" :label-width="100" :rules="formValidate">
<t-drawer :visible.sync="modalVisible" :header="modalTitle" placement="right" size="500px" :closeOnOverlayClick="false" @close="modalVisible=false">
<t-form ref="formAdd" :data="formAdd" :labelWidth="120" :rules="formValidate">
<div v-if="showParent">
<FormItem label="上级分类" prop="parentId">
<t-form-item label="上级分类" name="parentId">
{{ parentTitle }}
<Input v-model="formAdd.parentId" clearable style="width:100%;display:none"/>
</FormItem>
<t-input v-model="formAdd.parentId" clearable style="width:100%;display:none"/>
</t-form-item>
</div>
<FormItem label="层级" prop="level" style="display:none">
<Input v-model="formAdd.level" clearable style="width:100%"/>
</FormItem>
<FormItem label="分类名称" prop="labelName">
<Input v-model="formAdd.labelName" maxlength="12" clearable style="width:100%"/>
</FormItem>
<FormItem label="排序值" prop="sortOrder" style="width:345px">
<InputNumber v-model="formAdd.sortOrder" :min="1"></InputNumber>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible=false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="submit">提交</Button>
</div>
</Modal>
<t-form-item label="层级" name="level" style="display:none">
<t-input v-model="formAdd.level" clearable style="width:100%"/>
</t-form-item>
<t-form-item label="分类名称" name="labelName">
<t-input v-model="formAdd.labelName" maxlength="12" clearable style="width:100%"/>
</t-form-item>
<t-form-item label="排序值" name="sortOrder" style="width:345px">
<t-input-number v-model="formAdd.sortOrder" :min="1"></t-input-number>
</t-form-item>
</t-form>
<template #footer>
<t-button variant="text" @click="modalVisible=false">取消</t-button>
<t-button theme="primary" :loading="submitLoading" @click="submit">提交</t-button>
</template>
</t-drawer>
</Card>
</div>
</template>
<script>
import * as API_Goods from "@/api/goods";
import TreeTable from "@/views/my-components/tree-table/Table/Table";
import { regular } from "@/utils";
import {VARCHAR20} from "../../../utils/regular";
export default {
name: "store-category",
components: {
TreeTable
},
data() {
return {
@@ -94,18 +89,16 @@ export default {
columns: [
{
title: "分类名称",
key: "labelName",
colKey: "labelName",
align: "left",
minWidth: "120px",
minWidth: 120,
},
{
title: "操作",
key: "action",
colKey: "action",
align: "left",
headerAlign: "center",
width: "280px",
type: "template",
template: "action",
width: 280,
}
],
// 表格数据
@@ -132,7 +125,7 @@ export default {
this.modalType = 0;
this.modalTitle = "添加子分类";
this.parentTitle = v.labelName;
this.formAdd.level = eval(v.level + "+1");
this.formAdd.level = Number(v.level) + 1;
this.formAdd.labelName = "";
this.showParent = true;
delete this.formAdd.id;
@@ -167,11 +160,10 @@ export default {
},
//提交编辑和添加
submit() {
this.$refs.formAdd.validate(valid => {
if (valid) {
this.$refs.formAdd.validate().then((valid) => {
if (valid === true) {
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete this.formAdd.id;
API_Goods.addShopGoodsLabel(this.formAdd).then((res) => {
this.submitLoading = false;
@@ -182,7 +174,6 @@ export default {
}
});
} else {
// 编辑
API_Goods.editShopGoodsLabel(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
@@ -217,7 +208,7 @@ export default {
// 获取分类
getAllList() {
this.loading = true;
API_Goods.getShopGoodsLabelList(this.searchForm).then((res) => {
API_Goods.getShopGoodsLabelList().then((res) => {
this.loading = false;
if (res.success) {
res.result.forEach(firstCate => {
@@ -238,7 +229,7 @@ export default {
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-table-wrapper {
::v-deep .t-table__content {
overflow: auto;
}
.table {

View File

@@ -81,7 +81,7 @@
justify-content: flex-start;
flex-wrap: wrap;
>.ivu-form {
>.t-form {
flex-wrap: wrap !important;
}
@@ -139,11 +139,11 @@ div.base-info-item {
justify-content: flex-start;
width: 100%;
>.ivu-card-body {
>.t-card__body {
width: 100%;
}
.ivu-card-body {
.t-card__body {
width: 100%;
justify-content: center;
align-items: flex-start;
@@ -289,7 +289,7 @@ div.base-info-item {
text-align: center;
z-index: 999;
>.ivu-btn {
>.t-button {
margin: 0 10px;
}
}
@@ -393,8 +393,8 @@ div.base-info-item {
margin: 0 2px;
}
.required {
::v-deep .ivu-form-item-label::before {
.required {
::v-deep .t-form__label::before {
content: "*";
display: inline-block;
margin-right: 4px;

View File

@@ -137,7 +137,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -473,7 +473,7 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.searchForm.categoryPath = this.category ? this.category.join(",") : null;
this.getDataList();
},
@@ -482,7 +482,7 @@ export default {
this.searchForm = {};
this.category = [];
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
// 重新加载数据
this.getDataList();
},

View File

@@ -1,36 +1,25 @@
<template>
<div class="search">
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form mb_10"
@keydown.enter.native="handleSearch">
<Form-item label="商品名称" prop="goodsName">
<Input type="text" v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="商品编号" prop="id">
<Input
type="text"
v-model="searchForm.id"
placeholder="商品编号"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item style="margin-left: -35px" class="br">
<Button @click="handleSearch" type="primary" icon="ios-search"
>搜索</Button
>
<Button @click="handleReset">重置</Button>
</Form-item>
</Form>
</Card>
<Card>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" class="mt_10"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage"
@on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small" show-total show-elevator
show-sizer></Page>
</Row>
</Card>
<t-card>
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form mb_10">
<t-form-item label="商品名称" name="goodsName">
<t-input v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable style="width: 240px" />
</t-form-item>
<t-form-item label="商品编号" name="id">
<t-input v-model="searchForm.id" placeholder="商品编号" clearable style="width: 200px" />
</t-form-item>
<t-form-item style="margin-left: -35px" class="br">
<t-button @click="handleSearch" theme="primary">搜索</t-button>
<t-button @click="handleReset" style="margin-left:8px">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<t-table :loading="loading" :columns="tColumns" :data="data" rowKey="id" class="mt_10"></t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" @change="({ current }) => changePage(current)" @page-size-change="(size) => changePageSize(size)" :pageSizeOptions="[20, 50, 100]" size="small" showJumper showPageSize />
</div>
</t-card>
</div>
</template>
@@ -45,7 +34,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
saveType: "TEMPLATE",
@@ -151,6 +140,20 @@ export default {
total: 0, // 表单数据总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
methods: {
init() {
// 初始化数据
@@ -194,15 +197,20 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.$refs.searchForm.resetFields();
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
// 重新加载数据
this.searchForm = {
pageNumber: 1,
pageSize: 20,
sort: "create_time",
order: "desc",
saveType: "TEMPLATE",
goodsName: "",
id: ""
};
this.getDataList();
},
// 获取列表数据

View File

@@ -1,6 +1,6 @@
<template>
<div class="search">
<Card>
<Card class="mb_10">
<Row @keydown.enter.native="handleSearch">
<Form

View File

@@ -141,7 +141,7 @@ export default {
saveType: "TEMPLATE",
sort: "create_time",
order: "desc",
pageSize: 10,
pageSize: 20,
pageNumber: 1,
},
templateTotal: 0,
@@ -254,7 +254,7 @@ export default {
</script>
<style lang="scss" scoped>
@import "./addGoods.scss";
::v-deep .ivu-scroll-container {
::v-deep .t-scrollbar__view {
height: 450px !important;
}
</style>

View File

@@ -170,12 +170,12 @@
<div slot="content">
<Form>
<div v-for="(item, $index) in skuInfo" :key="$index" class="sku-item-content">
<Card :bordered="true" class="ivu-card-body">
<Card :bordered="true">
<a slot="extra" style="margin-left: 6px">
<Icon size="20" type="md-trash" @click="handleCloseSkuItem($index, item)"></Icon>
</a>
<div>
<div style="display: flex;margin-bottom: 10px;font-weight: bold">规格项</div>
<div class="flex mb_10 fw_bold">规格项</div>
<FormItem class="sku-item-content-val flex" label="">
<div>
@@ -184,15 +184,15 @@
@on-change="editSkuItem(item.name, $index, item)">
</AutoComplete>
<iSwitch v-if="$index === 0" style="margin-left: 10px" size="small"
@on-change="changeSkuOpenImage" v-model="openImage" /><span v-if="$index === 0"
<t-switch v-if="$index === 0" class="ml_10" size="small"
@change="changeSkuOpenImage" v-model="openImage" /><span v-if="$index === 0"
style="margin-left: 5px">添加规格图片</span>
</div>
</FormItem>
</div>
<div class="sku-val">
<div style="margin-bottom: 10px;font-weight: bold;display: flex">规格值 (输入完成后,鼠标点击其他地方后生效)</div>
<div class="flex mb_10 fw_bold">规格值 (输入完成后,鼠标点击其他地方后生效)</div>
<Form :model="item" class="flex">
<!--规格值文本列表-->
<FormItem v-for="(val, index) in item.spec_values" :key="index"
@@ -275,9 +275,6 @@
<div slot="content" :class="needToloadSku ? 'mask' : ''">
<Table :columns="skuTableColumn" :data="skuTableData" class="mt_10" style="
width: 100%;
.ivu-table-overflowX {
overflow-x: hidden;
}
">
<template slot="sn" slot-scope="{ row }">
<Input v-model="row.sn" clearable placeholder="请输入货号"
@@ -492,18 +489,18 @@ export default {
data() {
// 表单验证项,商品价格
const checkPrice = (rule, value, callback) => {
let err = null;
if (!value && value !== 0) {
return callback(new Error("商品价格不能为空"));
}
setTimeout(() => {
if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
err = new Error("商品价格不能为空");
} else if (!regular.money.test(value)) {
err = new Error("请输入正整数或者两位小数");
} else if (parseFloat(value) > 99999999) {
callback(new Error("商品价格设置超过上限值"));
} else {
callback();
err = new Error("商品价格设置超过上限值");
}
}, 1000);
if (typeof callback === 'function') {
return err ? callback(err) : callback();
}
return err || true;
};
return {
regular,
@@ -2199,7 +2196,7 @@ export default {
</style>
<style scoped>
.ivu-select .ivu-select-dropdown {
::v-deep .t-popup__content {
overflow: hidden !important;
}

View File

@@ -11,7 +11,7 @@ h4 {
margin: 20px 0;
font-size: 18px;
}
::v-deep .ivu-icon {
::v-deep .t-icon {
margin-right: 10px;
}
.rate-box {

View File

@@ -27,32 +27,15 @@
<div class="rate-box">
<div>
<i-circle :size="120" stroke-color="#fecb89" :trail-width="4" :stroke-width="5"
:percent="(userData.serviceScore * 20)" stroke-linecap="square">
<div class="demo-Circle-custom">
<p class="bold">{{ userData.serviceScore }}</p>
</div>
</i-circle>
<t-progress type="circle" :percentage="(userData.serviceScore * 20)" :label="userData.serviceScore + '分'" />
<h5>服务得分</h5>
</div>
<div>
<i-circle :size="120" stroke-color="#a7c5eb" :trail-width="4" :stroke-width="5"
:percent="(userData.deliveryScore * 20)" stroke-linecap="square">
<div>
<p class="bold">{{ userData.deliveryScore }}</p>
</div>
</i-circle>
<t-progress type="circle" :percentage="(userData.deliveryScore * 20)" :label="userData.deliveryScore + '分'" />
<h5>交货得分</h5>
</div>
<div>
<i-circle :size="120" stroke-color="#848ccf" :trail-width="4" :stroke-width="5"
:percent="(userData.descriptionScore * 20)" stroke-linecap="square">
<div>
<p class="bold">{{ userData.descriptionScore }}</p>
</div>
</i-circle>
<t-progress type="circle" :percentage="(userData.descriptionScore * 20)" :label="userData.descriptionScore + '分'" />
<h5>评价得分</h5>
</div>
</div>

View File

@@ -32,7 +32,7 @@ export default {
params: {
// 请求参数
pageNumber: 1,
pageSize: 10,
pageSize: 20,
storeName: "",
},
dateList: [

View File

@@ -215,7 +215,7 @@ export default {
margin: 0 4px;
}
}
::v-deep .ivu-modal-body {
::v-deep .t-dialog__body {
height: 400px !important;
overflow: auto;
}

View File

@@ -80,11 +80,11 @@ export default {
};
</script>
<style scoped lang="scss">
::v-deep .ivu-modal {
::v-deep .t-dialog {
overflow: hidden;
height: 650px !important;
}
::v-deep .ivu-modal-body {
::v-deep .t-dialog__body {
width: 100%;
height: 500px;
overflow: hidden;

View File

@@ -70,11 +70,11 @@ export default {
width: 100%;
}
::v-deep .ivu-modal {
::v-deep .t-dialog {
overflow: hidden;
height: 650px !important;
}
::v-deep .ivu-modal-body {
::v-deep .t-dialog__body {
width: 100%;
height: 500px;
overflow: hidden;

View File

@@ -36,11 +36,11 @@
}
}
}
::v-deep .ivu-scroll-container {
::v-deep .t-is-scrollbar .t-scrollbar__bar {
width: 100% !important;
height: 400px !important;
}
::v-deep .ivu-scroll-content {
::v-deep .t-scrollbar__view {
/* */
display: flex;
flex-wrap: wrap;

View File

@@ -33,11 +33,11 @@ export default {
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-card-body {
::v-deep .t-card__body {
height: 414px;
overflow: auto;
}
.ivu-table-wrapper ivu-table-wrapper-with-border {
::v-deep .t-table__content {
height: 300px !important;
}
.list {
@@ -69,11 +69,11 @@ export default {
height: 416px;
overflow: hidden;
}
::v-deep .ivu-table {
::v-deep .t-table {
height: 300px !important;
overflow: auto;
}
::v-deep .ivu-card-body {
::v-deep .t-card__body {
padding: 0;
height: auto;
}

View File

@@ -40,7 +40,7 @@ export default {
total: "", // 总数
params: { // 请求参数
pageNumber: 1,
pageSize: 10,
pageSize: 20,
storeDisable: "OPEN",
storeName: "",
},

View File

@@ -1,61 +1,57 @@
<template>
<div class="login" @click="$refs.verify.show = false">
<Row type="flex" @keydown.enter.native="submitLogin">
<Col style="width: 368px">
<div class="login" @click.self="$refs.verify.show = false">
<div @keydown.enter="submitLogin" style="display:flex;justify-content:center">
<div style="width: 368px">
<Header />
<Row style="flex-direction: column">
<Tabs v-model="loginType">
<Tab-pane label="账号密码登录" name="passwordLogin">
<div style="display:flex;flex-direction: column">
<t-tabs :value="loginType" @change="val => loginType = val">
<t-tab-panel label="账号密码登录" value="passwordLogin">
<!--账号密码登录-->
<Form ref="usernameLoginForm" :model="form" :rules="rules" class="form">
<FormItem prop="username">
<Input v-model="form.username" prefix="ios-contact" clearable placeholder="请输入用户名"
autocomplete="off" />
</FormItem>
<FormItem prop="password">
<Input type="password" v-model="form.password" prefix="ios-lock" password
placeholder="请输入密码" autocomplete="off" />
</FormItem>
</Form>
<t-form ref="usernameLoginForm" :data="form" :rules="rules" class="form">
<t-form-item name="username">
<t-input v-model="form.username" clearable placeholder="请输入用户名" autocomplete="off" />
</t-form-item>
<t-form-item name="password">
<t-input type="password" v-model="form.password" placeholder="请输入密码" autocomplete="off" />
</t-form-item>
</t-form>
<div class="register">
<a @click="$router.push('forgetPassword')">忘记密码</a>
</div>
</Tab-pane>
<Tab-pane label="验证码登录" name="mobileLogin">
</t-tab-panel>
<t-tab-panel label="验证码登录" value="mobileLogin">
<!-- 验证码登录 -->
<Form ref="formSms" :model="formSms" :rules="ruleInline" @click.self='$refs.verify.show = false'>
<FormItem prop="mobile">
<i-input type="text" maxlength="11" v-model="formSms.mobile" clearable placeholder="手机号">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
<FormItem prop="code">
<i-input type="text" v-model="formSms.code" placeholder="手机验证码">
<Icon type="ios-text-outline" style="font-weight: bold" slot="prepend" />
<Button slot="append" @click="sendCode" :loading="sendCodeLoading">{{ codeMsg }}</Button>
</i-input>
</FormItem>
<FormItem>
<t-form ref="formSms" :data="formSms" :rules="ruleInline" @click.self='$refs.verify.show = false'>
<t-form-item name="mobile">
<t-input type="text" maxlength="11" v-model="formSms.mobile" clearable placeholder="手机号" />
</t-form-item>
<t-form-item name="code">
<div style="display:flex; align-items:center">
<t-input type="text" v-model="formSms.code" placeholder="手机验证码" style="flex:1" />
<t-button style="margin-left:8px" @click="sendCode" :loading="sendCodeLoading">{{ codeMsg }}</t-button>
</div>
</t-form-item>
<t-form-item>
<!-- <Button @click.stop="verifyBtnClick" long :type="verifyStatus ? 'success' : 'default'">{{ verifyStatus ?
'验证通过' :
'点击完成安全验证' }}
</Button> -->
</FormItem>
</Form>
</Tab-pane>
</Tabs>
<Row>
</t-form-item>
</t-form>
</t-tab-panel>
</t-tabs>
<div>
<div class="login-btn" type="primary" size="large" :loading="loading" @click="submitLogin" long>
<span v-if="!loading">登录</span>
<span v-else>登录中</span>
</div>
</Row>
</Row>
</div>
</div>
<Footer />
<!-- 拼图验证码 -->
<verify ref="verify" class="verify-con" verifyType="LOGIN" @change="verifyChange"></verify>
</Col>
</Row>
</div>
</div>
</div>
</template>
@@ -214,27 +210,32 @@ export default {
submitLogin() {
// 登录提交
if (this.loginType == 'passwordLogin') {
this.$refs.usernameLoginForm.validate((valid) => {
if (valid) {
this.$refs.verify.init();
const res = this.$refs.usernameLoginForm && this.$refs.usernameLoginForm.validate()
if (res && typeof res.then === 'function') {
res.then(valid => { if (valid === true || valid) this.$refs.verify.init() })
} else if (res === true || res) {
this.$refs.verify.init()
}
});
} else if (this.loginType == 'mobileLogin') {
this.$refs['formSms'].validate((valid) => {
if (valid) {
this.loading = true;
const res = this.$refs['formSms'] && this.$refs['formSms'].validate()
const proceed = (valid) => {
if (valid === true || valid) {
this.loading = true
storeSmsLogin(this.formSms).then(res => {
this.loading = false;
this.loading = false
if (res.success) {
this.afterLogin(res)
}
}).catch(() => {
this.loading = false;
this.loading = false
})
}
})
}
if (res && typeof res.then === 'function') {
res.then(proceed)
} else {
proceed(res)
}
}
},
verifyChange(con) {

View File

@@ -2,7 +2,7 @@
@import "./styles/menu.scss";
</style>
<template>
<div class="ivu-shrinkable-menu">
<div class="menu-container">
<!-- 一级菜单 -->
<Menu ref="sideMenu" width="80px" theme="dark" :active-name="currNav" @on-select="selectNav">
<MenuItem v-for="(item, i) in navList" :key="i" :name="item.name">
@@ -17,7 +17,7 @@
@on-select="changeMenu"
>
<template v-for="item in menuList">
<MenuGroup :title="item.title" :key="item.id" style="padding-left:0;">
<MenuGroup :title="item.title" style="padding-left:0;">
<MenuItem :name="menu.name" v-for="menu in item.children" :key="menu.name">
{{menu.title}}
</MenuItem>
@@ -73,7 +73,8 @@ export default {
};
</script>
<style lang="scss" scoped>
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
::v-deep .t-menu--dark.t-menu--vertical .t-menu__item.t-is-active,
::v-deep .t-menu--dark.t-menu--vertical .t-submenu__title.t-is-active{
color: $theme_color;
}
</style>

View File

@@ -1,25 +1,17 @@
.ivu-shrinkable-menu{
.menu-container{
height: calc(100% - 60px);
width: 180px;
display: flex;
}
.ivu-btn-text:hover {
background-color: rgba(255,255,255,.2) !important;
}
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
background-color: #fff;
&:hover{
background-color: #fff;
}
}
.ivu-menu-vertical{
::v-deep .t-menu {
overflow-y: auto;
}
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
::v-deep .t-menu--dark.t-menu--vertical .t-menu__item.t-is-active,
::v-deep .t-menu--dark.t-menu--vertical .t-submenu__title.t-is-active {
background-color: #fff;
color: #ed3f14;
}
::v-deep .ivu-menu-vertical .ivu-menu-item-group-title{
::v-deep .t-menu .t-menu-group__title{
height: 40px;
line-height: 40px;
padding-left: 20px;

View File

@@ -266,8 +266,8 @@ export default {
}
}
.ivu-tag-primary{
::v-deep .ivu-tag-dot-inner{
.t-tag.t-tag--primary{
::v-deep .t-tag__dot .t-tag__dot-inner{
background: $theme_color !important;
}
}

View File

@@ -152,7 +152,7 @@
.options {
.ivu-select-dropdown {
::v-deep .t-popup__content {
transform-origin: center top 0px;
position: absolute;
top: 45px !important;

View File

@@ -8,57 +8,92 @@
<Form-item label="商品名称" prop="goodsName">
<Input type="text" v-model="searchForm.goodsName" clearable placeholder="请输入商品名" style="width: 240px" />
</Form-item>
<Form-item label="评价" prop="orderStatus">
<Select v-model="searchForm.grade" placeholder="请选择" clearable style="width: 240px">
<Option value="GOOD">好评</Option>
<Option value="MODERATE">中评</Option>
<Option value="WORSE">差评</Option>
</Select>
</Form-item>
<Form-item label="评论日期">
<DatePicker v-model="selectDate" type="datetimerange" format="yyyy-MM-dd HH:mm:ss" clearable @on-change="selectDateRange" placeholder="选择起始时间" style="width: 240px"></DatePicker>
<DatePicker v-model="selectDate" type="datetimerange" format="yyyy-MM-dd HH:mm:ss" clearable @on-change="selectDateRange" placeholder="选择起始时间" style="width: 360px"></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Card>
<Card>
<Tabs :value="gradeTab" @on-click="onTabClick">
<TabPane label="全部" name="ALL" />
<TabPane label="好评" name="GOOD" />
<TabPane label="中评" name="MODERATE" />
<TabPane label="差评" name="WORSE" />
</Tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" class="mt_10"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small"
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small"
show-total show-elevator show-sizer></Page>
</Row>
</Card>
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="500">
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
<FormItem label="评价内容">
<span v-if="!content">暂无评价</span>
<span v-else>
<t-drawer :visible.sync="modalVisible" :header="modalTitle" placement="right" size="800px" @close="modalVisible = false">
<div class="info-list" style="overflow: hidden">
<div class="left-container">
<div class="product">
<img class="img" :src="infoData.goodsImage">
</div>
<div class="show">
<label>页面展示</label>
<t-switch size="large" :customValue="['OPEN','CLOSE']" :label="['展示','隐藏']" v-model="infoData.status" @change="changeSwitchView" style="margin-top: 3px" />
</div>
</div>
<div class="right-container">
<div class="border-b">{{ infoData.goodsName }}</div>
<div class="border-b">
<div class="div-height"> 店铺名称{{ infoData.storeName }}</div>
<div class="div-height"> 订单号{{ infoData.orderNo }}</div>
</div>
<div class="border-b">
<t-list>
<t-list-item>
<div style="display: flex; align-items: flex-start">
<t-avatar :image="infoData.memberProfile" size="48px" />
<div style="margin-left: 12px">
<div>{{ infoData.memberName }}</div>
<div style="color: #666">{{ infoData.content }}</div>
</div>
</div>
</t-list-item>
<t-list-item>
<div class="score-content">
<span>物流评分{{ infoData.deliveryScore }}</span>
<span>服务评分{{ infoData.serviceScore }}</span>
<span>描述评分{{ infoData.descriptionScore }}</span>
</div>
</t-list-item>
<t-list-item v-if="infoData.haveImage">
<div>评价图</div>
<div style="margin-left: 40px">
<template v-if="infoData.images && infoData.images.length">
<img style="width: 100px;height: 110px;margin-left: 2px" v-for="(img,index) in infoData.images.split(',')" :src="img" alt="" :key="index"/>
</template>
</div>
</t-list-item>
</t-list>
</div>
<div class="border-b" v-if="infoData.reply">
<div>
<Input v-model="content" type="textarea" maxlength="200" disabled :rows="4" clearable style="width:90%" />
<div>
<div style="float: left"> 商家回复</div>
<div style="margin-left: 60px">{{ infoData.reply }}</div>
</div>
</span>
</FormItem>
<FormItem label="评价图片" style="padding-top: 10px" v-if="detailInfo.haveImage == 1">
<upload-pic-thumb v-model="image" :disable="true" :remove="false" :isView="true"></upload-pic-thumb>
</FormItem>
<FormItem label="回复内容" prop="reply">
<Input v-if="replyStatus == false" v-model="form.reply" type="textarea" maxlength="200" :rows="4" clearable style="width:90%" />
<span v-else>
<Input v-model="form.reply" type="textarea" maxlength="200" disabled :rows="4" clearable style="width:90%" />
</span>
</FormItem>
<FormItem label="回复图片" prop="replyImage" style="padding-top: 18px" v-if="detailInfo.haveReplyImage == 1 || replyStatus == false">
<upload-pic-thumb v-if="replyStatus == false" v-model="form.replyImage" :limit="5"></upload-pic-thumb>
<upload-pic-thumb v-else v-model="form.replyImage" :disable="true" :remove="false"></upload-pic-thumb>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button v-if="replyStatus == false" type="primary" :loading="submitLoading" @click="handleSubmit">回复
</Button>
<div v-if="infoData.haveReplyImage">
<div style="margin-left: 60px">
<template v-if="infoData.replyImage && infoData.replyImage.length">
<img style="width: 100px;height: 110px" v-for="(img,index) in infoData.replyImage.split(',')" :key="index" :src="img" alt=""/>
</template>
</div>
</Modal>
</div>
</div>
</div>
</div>
</div>
<template #footer>
<t-button theme="primary" @click="modalVisible = false">返回</t-button>
</template>
</t-drawer>
</div>
</template>
@@ -73,6 +108,7 @@ export default {
},
data() {
return {
infoData: { status: 'CLOSE' },
detailInfo: {}, // 详情信息
image: [], //评价图片
replyStatus: false, //回复状态
@@ -83,13 +119,14 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startTime: "", // 起始时间
endTime: "", // 终止时间
},
selectDate: null,
gradeTab: "ALL",
selectDate: [],
form: {
replyImage: [],
reply: "",
@@ -125,11 +162,11 @@ export default {
width: 100,
render: (h, params) => {
if (params.row.grade == "GOOD") {
return h("Tag", { props: { color: "green" } }, "好评");
return h("div", "好评");
} else if (params.row.grade == "MODERATE") {
return h("Tag", { props: { color: "orange" } }, "中评");
return h("div", "中评");
} else {
return h("Tag", { props: { color: "red" } }, "差评");
return h("div", "差评");
}
},
},
@@ -138,11 +175,7 @@ export default {
key: "status",
width: 100,
render: (h, params) => {
if (params.row.status === "OPEN") {
return h("Tag", { props: { color: "green" } }, "展示");
} else {
return h("Tag", { props: { color: "red" } }, "隐藏");
}
return h("div", params.row.status === "OPEN" ? "展示" : "隐藏");
},
},
{
@@ -150,18 +183,15 @@ export default {
key: "replyStatus",
width: 110,
render: (h, params) => {
if (params.row.replyStatus) {
return h("Tag", { props: { color: "green" } }, "已回复");
} else {
return h("Tag", { props: { color: "blue" } }, "未回复");
}
return h("div", params.row.replyStatus ? "已回复" : "未回复");
},
},
{
title: "创建日期",
key: "createTime",
width: 170,
minWidth: 220,
tooltip: true,
},
{
@@ -215,14 +245,19 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.searchForm = {};
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.searchForm.startTime = "";
this.searchForm.endTime = "";
this.gradeTab = "ALL";
delete this.searchForm.grade;
this.selectDate = [];
this.getDataList();
},
// 清除选中状态
@@ -247,6 +282,16 @@ export default {
}
});
},
onTabClick(name) {
this.gradeTab = name;
if (name === "ALL") {
delete this.searchForm.grade;
} else {
this.searchForm.grade = name;
}
this.searchForm.pageNumber = 1;
this.getDataList();
},
//回复
handleSubmit() {
this.$refs.form.validate((valid) => {
@@ -264,26 +309,23 @@ export default {
},
// 获取详情
detail(v) {
this.form.replyImage = [];
this.loading = true;
API_Member.getMemberInfoReview(v.id).then((res) => {
this.loading = false;
if (res.success) {
//赋值
this.form.id = res.result.id;
this.content = res.result.content;
this.form.reply = res.result.reply;
this.replyStatus = res.result.replyStatus;
if (res.result.images) {
this.image = (res.result.images || "").split(",");
}
if (res.result.replyImage) {
this.form.replyImage = (res.result.replyImage || "").split(",");
}
this.detailInfo = res.result;
//弹出框
this.modalVisible = true;
this.modalTitle = "详细";
this.modalTitle = `用户${v.memberName}的评价详情`;
API_Member.getMemberInfoReview(v.id).then((res) => {
if (res && res.success && res.result) {
const data = res.result || {};
const s = data.status;
data.status = (s === 'OPEN' || s === 'CLOSE') ? s : (s ? 'OPEN' : 'CLOSE');
this.infoData = data;
}
});
},
changeSwitchView(val) {
const status = val;
API_Member.updateMemberReview(this.infoData.id, { status }).then((res) => {
if (res && res.success) {
this.$Message.success("修改成功");
this.init();
}
});
},
@@ -296,4 +338,49 @@ export default {
<style lang="scss">
// 建议引入通用样式 可删除下面样式代码
@import "@/styles/table-common.scss";
.left-container {
float: left;
}
.right-container {
float: left;
margin-left: 50px;
}
.img {
width: 100%;
height: 100%;
}
img {
vertical-align: middle;
border-style: none;
}
.product {
width: 140px;
height: 160px;
border: 1px solid #d9d9d9;
border-radius: 3px;
}
.show {
margin-top: 15px;
}
label {
font-size: 12px;
color: #666;
margin-top: 4px;
display: block;
float: left;
margin-right: 2px;
}
.border-b {
border-bottom: 1px solid #e9e9e9;
width: 500px;
overflow: hidden;
position: relative;
margin-top: 12px;
}
.div-height {
line-height: 25px;
}
.score-content {
margin: 5px 0;
}
</style>

View File

@@ -55,7 +55,7 @@
:page-size="params.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[5,10]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -197,7 +197,7 @@
params: { // 请求消息列表参数
status: "UN_READY",
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc" // 默认排序方式
},
@@ -259,7 +259,7 @@
h("Icon", {
props: {
type: "md-time",
size: 16
size: '16'
},
style: {
margin: "0 5px 3px 0"

View File

@@ -32,7 +32,7 @@ export default {
if (res.success) {
const arr = res.result;
this.filterData(arr)
this.department = arr
this.department = Array.isArray(arr) ? arr : []
}
});
},
@@ -49,14 +49,15 @@ export default {
this.selectDep = [];
},
// 处理部门数据
filterData (data) {
filterData(data) {
if (!Array.isArray(data)) return
data.forEach(e => {
e.value = e.id;
e.label = e.title;
if (e.children) {
e.value = e.id
e.label = e.title
if (!Array.isArray(e.children)) {
e.children = []
} else if (e.children.length) {
this.filterData(e.children)
} else {
return
}
})
}

View File

@@ -134,8 +134,8 @@ export default {
</script>
<style lang="scss" scoped>
.set-password .ivu-poptip,
.set-password .ivu-poptip-rel {
.set-password ::v-deep .t-popconfirm,
.set-password ::v-deep .t-popconfirm__reference {
display: block;
}
.password-tip-none {

View File

@@ -1,7 +1,7 @@
import Checkbox from '../Checkbox/Checkbox'; // eslint-disable-line
// import Radio from '../Radio/Radio'; // eslint-disable-line
import { mixins } from './utils';
import { Radio } from 'view-design'; // eslint-disable-line
const Radio = { functional: true, render(h, ctx){ return h('Radio', ctx.data, ctx.children) } }
/* eslint-disable no-underscore-dangle */
export default {

View File

@@ -174,7 +174,7 @@ export default {
display: flex;
align-items: center;
justify-content: center;
.ivu-icon {
.t-icon {
font-size: 20px;
}
}

View File

@@ -1,76 +1,71 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="会员名称" prop="memberName">
<Input
type="text"
<t-card>
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form">
<t-form-item label="会员名称" name="memberName">
<t-input
v-model="searchForm.memberName"
clearable
placeholder="请输入会员名称"
style="width: 240px"
/>
</Form-item>
<Form-item label="订单号" prop="orderSn">
<Input
type="text"
</t-form-item>
<t-form-item label="订单号" name="orderSn">
<t-input
v-model="searchForm.orderSn"
clearable
placeholder="请输入订单号"
style="width: 240px"
/>
</Form-item>
<Form-item label="状态" prop="status">
<Select v-model="searchForm.status" placeholder="请选择订单状态" clearable style="width: 240px">
<Option value="NEW">新投诉</Option>
<Option value="CANCEL">已撤销</Option>
<Option value="WAIT_APPEAL">待申诉</Option>
<Option value="COMMUNICATION">对话中</Option>
<Option value="WAIT_ARBITRATION">等待仲裁</Option>
<Option value="COMPLETE">已完成</Option>
</Select>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Row>
</Card>
<Card>
<Table
</t-form-item>
<t-form-item label="状态" name="status">
<t-select v-model="searchForm.status" placeholder="请选择订单状态" clearable style="width: 240px">
<t-option value="NEW" label="新投诉" />
<t-option value="CANCEL" label="已撤销" />
<t-option value="WAIT_APPEAL" label="待申诉" />
<t-option value="COMMUNICATION" label="对话中" />
<t-option value="WAIT_ARBITRATION" label="等待仲裁" />
<t-option value="COMPLETE" label="已完成" />
</t-select>
</t-form-item>
<t-form-item>
<t-button @click="handleSearch" theme="primary" class="search-btn">搜索</t-button>
<t-button @click="handleReset" class="search-btn" style="margin-left: 8px">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<t-table
:loading="loading"
border
:columns="columns"
:data="data"
class="mt_10"
ref="table"
:columns="tColumns"
:data="data"
rowKey="id"
>
<template slot-scope="{row}" slot="goodsName">
<template #goodsName="{ row }">
<a class="mr_10" @click="linkTo(row.goodsId,row.skuId)">{{row.goodsName}}</a>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<t-popup trigger="hover" placement="top">
<template #content>
<vue-qr :text="wapLinkTo(row.goodsId,row.skuId)" :margin="0" colorDark="#000" colorLight="#fff" :size="150"></vue-qr>
</div>
<img src="../../../assets/qrcode.svg" style="vertical-align:bottom;" class="hover-pointer" width="20" height="20" alt="">
</Poptip>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
<img src="../../../assets/qrcode.svg" style="vertical-align:bottom;" class="hover-pointer" width="20" height="20" alt="">
</t-popup>
</template>
</t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
:total="Number(total)"
:pageSize="searchForm.pageSize"
:pageSizeOptions="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
showJumper
showPageSize
@change="({ current }) => changePage(current)"
@page-size-change="(size) => changePageSize(size)"
/>
</div>
</t-card>
</div>
</template>
@@ -192,6 +187,21 @@
total: 0, // 表单数据总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
methods: {
// 初始化数据
init() {

View File

@@ -381,7 +381,7 @@ export default {
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-col {
::v-deep .t-col {
width: 100% !important;
}

View File

@@ -1,68 +1,66 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="商品" prop="goodsName">
<Input
type="text"
<t-card>
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form">
<t-form-item label="商品" name="goodsName">
<t-input
v-model="searchForm.goodsName"
clearable
placeholder="请输入商品名称"
style="width: 240px"
/>
</Form-item>
<Form-item label="会员名称" prop="memberName">
<Input
type="text"
</t-form-item>
<t-form-item label="会员名称" name="memberName">
<t-input
v-model="searchForm.memberName"
clearable
placeholder="请输入会员名称"
style="width: 240px"
/>
</Form-item>
<Form-item label="订单编号" prop="orderSn">
<Input
type="text"
</t-form-item>
<t-form-item label="订单编号" name="orderSn">
<t-input
v-model="searchForm.orderSn"
clearable
placeholder="请输入订单编号"
style="width: 240px"
/>
</Form-item>
</t-form-item>
<Form-item label="申请时间">
<DatePicker
<t-form-item label="申请时间">
<t-date-range-picker
v-model="selectDate"
type="datetimerange"
format="yyyy-MM-dd HH:mm:ss"
enableTimePicker
format="YYYY-MM-DD HH:mm:ss"
valueType="time-stamp"
clearable
@on-change="selectDateRange"
@change="selectDateRange"
placeholder="选择起始时间"
style="width: 240px"
></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Row>
</Card>
<Card>
style="width: 300px"
/>
</t-form-item>
<t-form-item>
<t-button @click="handleSearch" theme="primary" class="search-btn">搜索</t-button>
<t-button @click="handleReset" class="search-btn" style="margin-left: 8px">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="order-tab">
<t-tabs :value="currentStatus" @change="serviceStatusClick">
<t-tab-panel v-for="item in serviceStatusWithCount" :key="item.value" :label="item.title" :value="item.value"/>
</t-tabs>
</div>
<Table
<t-table
:loading="loading"
class="mt_10"
:columns="columns"
:columns="tColumns"
:data="data"
ref="table"
rowKey="sn"
>
<!-- 商品栏目格式化 -->
<template slot="goodsSlot" slot-scope="{row}">
<template #goodsSlot="{ row }">
<div style="margin-top: 5px;height: 60px; display: flex;">
<div style="">
<img :src="row.goodsImage" style="height: 50px;margin-top: 3px">
@@ -77,22 +75,21 @@
</div>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
</t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
:total="Number(total)"
:pageSize="searchForm.pageSize"
:pageSizeOptions="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
showJumper
showPageSize
@change="({ current }) => changePage(current)"
@page-size-change="(size) => changePageSize(size)"
/>
</div>
</t-card>
</div>
</template>
@@ -118,7 +115,7 @@
memberName:"",
goodsName:""
},
selectDate: null,
selectDate: [],
columns: [
{
@@ -134,7 +131,6 @@
{
title: "商品",
key: "sn",
minWidth: 200,
slot: "goodsSlot",
@@ -236,6 +232,35 @@
afterSaleNumData: {} // 售后数量统计数据
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
if (nc.render && !nc.cell) {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
},
serviceStatusWithCount() {
return [
{title: '全部', value: ''},
{title: `申请售后${this.afterSaleNumData.applyNum ? '(' + this.afterSaleNumData.applyNum + ')' : ''}`, value: 'APPLY'},
{title: `通过售后${this.afterSaleNumData.passNum ? '(' + this.afterSaleNumData.passNum + ')' : ''}`, value: 'PASS'},
{title: `拒绝售后${this.afterSaleNumData.refuseNum ? '(' + this.afterSaleNumData.refuseNum + ')' : ''}`, value: 'REFUSE'},
{title: `待收货${this.afterSaleNumData.buyerReturnNum ? '(' + this.afterSaleNumData.buyerReturnNum + ')' : ''}`, value: 'BUYER_RETURN'},
{title: `确认收货${this.afterSaleNumData.sellerConfirmNum ? '(' + this.afterSaleNumData.sellerConfirmNum + ')' : ''}`, value: 'SELLER_CONFIRM'},
{title: `完成售后${this.afterSaleNumData.completeNum ? '(' + this.afterSaleNumData.completeNum + ')' : ''}`, value: 'COMPLETE'},
{title: `卖家终止售后${this.afterSaleNumData.sellerTerminationNum ? '(' + this.afterSaleNumData.sellerTerminationNum + ')' : ''}`, value: 'SELLER_TERMINATION'},
{title: `买家取消售后${this.afterSaleNumData.buyerCancelNum ? '(' + this.afterSaleNumData.buyerCancelNum + ')' : ''}`, value: 'BUYER_CANCEL'},
{title: `等待平台退款${this.afterSaleNumData.waitRefundNum ? '(' + this.afterSaleNumData.waitRefundNum + ')' : ''}`, value: 'WAIT_REFUND'}
];
}
},
methods: {
// 初始化数据
init() {
@@ -275,7 +300,7 @@
goodsName:""
}
this.searchForm = defaultForm;
this.selectDate = ''
this.selectDate = []
this.getDataList();
this.getAfterSaleNumData();
},
@@ -284,6 +309,9 @@
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
} else {
this.searchForm.startDate = '';
this.searchForm.endDate = '';
}
},
// 获取列表数据
@@ -320,8 +348,7 @@
// 售后筛选
serviceStatusClick(item) {
this.currentStatus = item;
// 如果是全部空字符串则删除serviceStatus字段
if (item === 0) {
if (item === '') {
delete this.searchForm.serviceStatus;
} else {
this.searchForm.serviceStatus = item;
@@ -333,23 +360,6 @@
mounted () {
this.init();
},
computed: {
// 带数量的售后状态
serviceStatusWithCount() {
return [
{title: '全部', value: ''},
{title: `申请售后${this.afterSaleNumData.applyNum ? '(' + this.afterSaleNumData.applyNum + ')' : ''}`, value: 'APPLY'},
{title: `通过售后${this.afterSaleNumData.passNum ? '(' + this.afterSaleNumData.passNum + ')' : ''}`, value: 'PASS'},
{title: `拒绝售后${this.afterSaleNumData.refuseNum ? '(' + this.afterSaleNumData.refuseNum + ')' : ''}`, value: 'REFUSE'},
{title: `待收货${this.afterSaleNumData.buyerReturnNum ? '(' + this.afterSaleNumData.buyerReturnNum + ')' : ''}`, value: 'BUYER_RETURN'},
{title: `确认收货${this.afterSaleNumData.sellerConfirmNum ? '(' + this.afterSaleNumData.sellerConfirmNum + ')' : ''}`, value: 'SELLER_CONFIRM'},
{title: `完成售后${this.afterSaleNumData.completeNum ? '(' + this.afterSaleNumData.completeNum + ')' : ''}`, value: 'COMPLETE'},
{title: `卖家终止售后${this.afterSaleNumData.sellerTerminationNum ? '(' + this.afterSaleNumData.sellerTerminationNum + ')' : ''}`, value: 'SELLER_TERMINATION'},
{title: `买家取消售后${this.afterSaleNumData.buyerCancelNum ? '(' + this.afterSaleNumData.buyerCancelNum + ')' : ''}`, value: 'BUYER_CANCEL'},
{title: `等待平台退款${this.afterSaleNumData.waitRefundNum ? '(' + this.afterSaleNumData.waitRefundNum + ')' : ''}`, value: 'WAIT_REFUND'}
];
}
},
// 页面缓存处理从该页面离开时修改KeepAlive为false保证进入该页面是刷新
beforeRouteLeave(to, from, next) {
from.meta.keepAlive = false
@@ -362,7 +372,7 @@
@import "@/styles/table-common.scss";
// Tab组件样式
.order-tab {
::v-deep .ivu-tabs-tab {
::v-deep .t-tabs__nav-item {
font-size: 14px;
}
}

View File

@@ -134,7 +134,6 @@
{
title: "商品",
key: "sn",
minWidth: 250,
sortable: false,
slot: "goodsSlot",

View File

@@ -536,7 +536,7 @@ export default {
};
</script>
<style lang="scss" scoped>
.ivu-row {
.t-row {
display: block !important;
}

View File

@@ -3,15 +3,12 @@
<Card style="height: 60px">
<div>
<Button v-if="allowOperation.editPrice" @click="modifyPrice" type="primary">调整价格</Button>
<Button v-if="allowOperation.editConsignee" @click="editAddress" type="primary">修改收货地址</Button>
<Button v-if="allowOperation.editConsignee" @click="editAddress" type="primary" ghost>修改收货地址</Button>
<Button v-if="allowOperation.showLogistics || orderPackage.length > 0" @click="checkLogistics" type="primary">查看物流</Button>
<Button @click="orderLogModal = true" type="primary">订单日志</Button>
<Button @click="orderLogModal = true" type="info" >订单日志</Button>
<Button @click="printOrder" type="primary" ghost style="float:right;">打印发货单</Button>
<Button v-if="allowOperation.take" @click="orderTake" type="primary">订单核销</Button>
<!-- <Button v-if="allowOperation.ship" @click="orderDeliver" type="primary">发货</Button> -->
<Button v-if="allowOperation.ship" @click="groupShip" type="primary">分包裹发货</Button>
<Button @click="sfPrint" type="primary" ghost
v-if="allowOperation.showLogistics && logisticsType == 'SHUNFENG'">下载面单</Button>
<Button @click="toPrint" type="primary" ghost
@@ -20,134 +17,80 @@
</div>
</Card>
<Card class="mt_10">
<Row>
<Col span="12">
<Card class="mt_10 clearfix">
<div style="width: 30%; float: left; margin-left: 20px">
<div class="div-item">
<div class="div-item-left">订单号</div>
<div class="div-item-right">{{ orderInfo.order.sn }}</div>
</div>
<div class="div-item">
<div class="div-item-left">订单来源</div>
<div class="div-item-right">
{{ orderInfo.order.clientType | clientTypeWay }}
<div class="div-item-right">{{ orderInfo.order.clientType | clientTypeWay }}</div>
</div>
<div class="div-item">
<div class="div-item-left">订单状态</div>
<div class="div-item-right">{{ orderInfo.orderStatusValue }}</div>
</div>
<div class="div-item">
<div class="div-item-left">下单时间</div>
<div class="div-item-right">{{ orderInfo.order.createTime }}</div>
</div>
</div>
<div style="width: 30%; float: left; margin-left: 20px">
<div class="div-item" v-if="orderInfo.order.needReceipt == false">
<div class="div-item-left">发票信息</div>
<div class="div-item-right">暂无发票信息</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
<div class="div-item-left">发票抬头</div>
<div class="div-item-right">{{ orderInfo.receipt && orderInfo.receipt.receiptTitle ? orderInfo.receipt.receiptTitle : '暂无' }}</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == true && orderInfo.receipt && orderInfo.receipt.taxpayerId">
<div class="div-item-left">发票税号</div>
<div class="div-item-right">{{ orderInfo.receipt && orderInfo.receipt.taxpayerId ? orderInfo.receipt.taxpayerId : '暂无' }}</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
<div class="div-item-left">发票内容</div>
<div class="div-item-right">{{ orderInfo.receipt && orderInfo.receipt.receiptContent ? orderInfo.receipt.receiptContent : '暂无' }}</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
<div class="div-item-left">发票金额</div>
<div class="div-item-right">
<priceColorScheme v-if="orderInfo.receipt && orderInfo.receipt.receiptPrice" :value="orderInfo.receipt.receiptPrice" :color="$mainColor" />
<span v-else>暂无</span>
</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
<div class="div-item-left">是否开票</div>
<div class="div-item-right">{{ orderInfo.receipt ? (orderInfo.receipt.receiptStatus == 0 ? '未开' : '已开') : '空' }}</div>
</div>
</div>
<div style="width: 36%; float: left">
<div class="div-item" v-if="orderInfo.order.deliveryMethod != 'SELF_PICK_UP'">
<div class="div-item-left">收货信息</div>
<div class="div-item-right">{{ orderInfo.order.consigneeName }} {{ orderInfo.order.consigneeMobile }} {{ orderInfo.order.consigneeAddressPath }} {{ orderInfo.order.consigneeDetail }}</div>
</div>
<div class="div-item" v-if="orderInfo.order.deliveryMethod == 'SELF_PICK_UP'">
<div class="div-item-left">自提信息</div>
<div class="div-item-right">{{ orderInfo.order.storeAddressPath }} {{ orderInfo.order.storeAddressMobile }}</div>
</div>
<div class="div-item">
<div class="div-item-left">支付方式</div>
<div class="div-item-right">{{ orderInfo.paymentMethodValue }}</div>
</div>
<div class="div-item">
<div class="div-item-left">买家留言</div>
<div class="div-item-right">{{ orderInfo.order.remark }}</div>
</div>
<div class="div-item">
<div class="div-item-left">订单备注</div>
<div class="div-item-right">{{ orderInfo.order.sellerRemark }}</div>
</div>
<div class="div-item">
<div class="div-item-left">订单状态</div>
<div class="div-item-right">
{{ orderInfo.orderStatusValue }}
</div>
</div>
<div class="div-item">
<div class="div-item-left">下单时间</div>
<div class="div-item-right">
{{ orderInfo.order.createTime }}
</div>
</div>
<div class="div-item" v-if="orderInfo.order.needReceipt == false">
<div class="div-item-left">发票信息</div>
<div class="div-item-right">暂无发票信息</div>
</div>
<template v-if="orderInfo.order.needReceipt == true && orderInfo.receipt">
<div class="div-item">
<div class="div-item-left">发票抬头</div>
<div class="div-item-right">
{{
orderInfo.receipt.receiptTitle
? orderInfo.receipt.receiptTitle
: "暂无"
}}
</div>
</div>
<div class="div-item" v-if="orderInfo.receipt.taxpayerId">
<div class="div-item-left">发票税号</div>
<div class="div-item-right">
{{
orderInfo.receipt.taxpayerId
? orderInfo.receipt.taxpayerId
: "暂无"
}}
</div>
</div>
<div class="div-item">
<div class="div-item-left">发票内容</div>
<div class="div-item-right">
{{
orderInfo.receipt.receiptContent
? orderInfo.receipt.receiptContent
: "暂无"
}}
</div>
</div>
<div class="div-item">
<div class="div-item-left">发票金额</div>
<div class="div-item-right">
<span v-if="orderInfo.receipt.receiptPrice"></span>{{
orderInfo.receipt.receiptPrice
? orderInfo.receipt.receiptPrice
: "暂无" | unitPrice
}}
</div>
</div>
<div class="div-item">
<div class="div-item-left">是否开票</div>
<div class="div-item-right">
{{ orderInfo.receipt.receiptStatus == 0 ? "未开" : "已开" }}
</div>
</div>
</template>
</Col>
<Col span="12">
<div class="div-item" v-if="orderInfo.order.deliveryMethod != 'SELF_PICK_UP'">
<div class="div-item-left">收货信息</div>
<div class="div-item-right">
{{ orderInfo.order.consigneeName }}
{{ orderInfo.order.consigneeMobile }}
{{ orderInfo.order.consigneeAddressPath }}
{{ orderInfo.order.consigneeDetail }}
</div>
</div>
<div class="div-item" v-if="orderInfo.order.deliveryMethod == 'SELF_PICK_UP'">
<div class="div-item-left">自提信息</div>
<div class="div-item-right">
{{ orderInfo.order.storeAddressPath }}
{{ orderInfo.order.storeAddressMobile }}
</div>
</div>
<div class="div-item">
<div class="div-item-left">支付方式</div>
<div class="div-item-right">
{{ orderInfo.paymentMethodValue }}
</div>
</div>
<div class="div-item">
<div class="div-item-left">买家留言</div>
<div class="div-item-right">{{ orderInfo.order.remark }}</div>
</div>
<div class="div-item" v-if="orderInfo.order.orderType != 'VIRTUAL'">
<div class="div-item-left">配送方式</div>
<div class="div-item-right">
{{
orderInfo.deliveryMethodValue
? orderInfo.deliveryMethodValue
: "暂无配送方式"
}}
<div class="div-item-right">{{ orderInfo.deliveryMethodValue ? orderInfo.deliveryMethodValue : '暂无配送方式' }}</div>
</div>
</div>
</Col>
</Row>
</Card>
<Card class="mt_10">
@@ -196,7 +139,7 @@
<li v-if="orderInfo.order.priceDetailDTO.couponPrice && orderInfo.order.priceDetailDTO.couponPrice > 0">
<span class="label">优惠券金额</span>
<span class="txt"> {{ orderInfo.order.priceDetailDTO.couponPrice | unitPrice('¥') }} </span>
<span class="txt"><priceColorScheme :value="orderInfo.order.priceDetailDTO.couponPrice" :color="$mainColor" /></span>
</li>
<li
v-if="orderInfo.order.priceDetailDTO.discountPriceDetail != undefined && orderInfo.order.priceDetailDTO.discountPriceDetail && orderInfo.order.priceDetailDTO.discountPriceDetail != null && orderInfo.order.priceDetailDTO.discountPriceDetail != ''">
@@ -252,7 +195,7 @@
</li>
<li>
<span class="label">应付金额</span>
<span class="txt flowPrice">¥{{ orderInfo.order.flowPrice | unitPrice }}</span>
<span class="txt flowPrice">¥{{ orderInfo.order.priceDetailDTO.flowPrice | unitPrice }}</span>
<!-- <template v-if="orderInfo.order.priceDetailDTO.discountPriceDetail != undefined && orderInfo.order.priceDetailDTO.discountPriceDetail && orderInfo.order.priceDetailDTO.discountPriceDetail != null && orderInfo.order.priceDetailDTO.discountPriceDetail != ''">
<Space style="height:20px;float: right;text-align: center;margin-left:30px;margin-right:53px;">
<Button type="primary" ghost size="small" @click="getOrderPrice()">优惠详情</Button>
@@ -349,19 +292,14 @@
<Button type="primary" @click="orderTakeSubmit">核销</Button>
</div>
</Modal>
<!-- 订单日志 -->
<Modal v-model="orderLogModal" width="60">
<p slot="header">
<span>订单日志</span>
</p>
<t-drawer :visible.sync="orderLogModal" header="订单日志" placement="right" size="500px" @close="orderLogModal = false">
<div class="order-log-div">
<Table :loading="loading" border :columns="orderLogColumns" :data="orderLogData" ref="table"></Table>
</div>
<div slot="footer" style="text-align: right">
<Button @click="orderLogModal = false">取消</Button>
</div>
</Modal>
<template #footer>
<t-button variant="text" @click="orderLogModal = false">取消</t-button>
</template>
</t-drawer>
<!-- 查询物流 -->
<Modal v-model="logisticsModal" width="40">
@@ -716,7 +654,7 @@ export default {
},
{
title: "优惠",
key: "num",
key: "promotionType",
minWidth: 100,
render: (h, params) => {
let resultText = "";

View File

@@ -1,124 +1,60 @@
<template>
<div class="search">
<Card>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="关键字" prop="keywords" style="display: block; width: 100%;">
<Input
type="text"
v-model="searchForm.keywords"
placeholder="请输入商品名称/收货人/收货人手机号/店铺名称"
clearable
style="width: 500px"
/>
</Form-item>
<Form-item label="订单编号" prop="orderSn">
<Input
type="text"
v-model="searchForm.orderSn"
clearable
placeholder="请输入订单编号"
style="width: 240px"
/>
</Form-item>
<Form-item label="会员名称" prop="buyerName">
<Input
type="text"
v-model="searchForm.buyerName"
clearable
placeholder="请输入会员名称"
style="width: 240px"
/>
</Form-item>
<Form-item label="收货人" prop="shipName">
<Input
type="text"
v-model="searchForm.shipName"
placeholder="请输入收货人姓名"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="订单类型" prop="orderType">
<Select
v-model="searchForm.orderPromotionType"
placeholder="请选择"
clearable
style="width: 240px"
>
<Option value="NORMAL">普通订单</Option>
<Option value="PINTUAN">拼团订单</Option>
<Option value="GIFT">赠品订单</Option>
<Option value="POINTS">积分订单</Option>
<Option value="KANJIA">砍价订单</Option>
</Select>
</Form-item>
<Form-item label="下单时间">
<DatePicker
v-model="selectDate"
type="datetimerange"
format="yyyy-MM-dd"
clearable
@on-change="selectDateRange"
placeholder="选择起始时间"
style="width: 240px"
></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn"
>搜索</Button
>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Card>
<Card>
<t-card class="mb_10">
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form">
<t-form-item label="关键字" name="keywords" style="display: block; width: 100%">
<t-input v-model="searchForm.keywords" placeholder="请输入商品名称/收货人/收货人手机号/店铺名称" clearable style="width: 500px" />
</t-form-item>
<t-form-item label="订单编号" name="orderSn">
<t-input v-model="searchForm.orderSn" clearable placeholder="请输入订单编号" style="width: 240px" />
</t-form-item>
<t-form-item label="会员名称" name="buyerName">
<t-input v-model="searchForm.buyerName" clearable placeholder="请输入会员名称" style="width: 240px" />
</t-form-item>
<t-form-item label="收货人" name="shipName">
<t-input v-model="searchForm.shipName" placeholder="请输入收货人姓名" clearable style="width: 240px" />
</t-form-item>
<t-form-item label="订单类型" name="orderType">
<t-select v-model="searchForm.orderPromotionType" placeholder="请选择" clearable style="width: 240px">
<t-option value="NORMAL" label="普通订单" />
<t-option value="PINTUAN" label="拼团订单" />
<t-option value="GIFT" label="赠品订单" />
<t-option value="POINTS" label="积分订单" />
<t-option value="KANJIA" label="砍价订单" />
</t-select>
</t-form-item>
<t-form-item label="下单时间">
<t-date-picker v-model="selectDate" mode="date" range format="YYYY-MM-DD" valueType="time-stamp" clearable @change="selectDateRange" placeholder="选择起始时间" style="width: 240px" />
</t-form-item>
<t-form-item>
<t-button theme="primary" class="search-btn" @click="handleSearch">搜索</t-button>
<t-button variant="outline" style="margin-left: 8px" @click="handleReset">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="order-tab">
<Tabs v-model="currentStatus" @on-click="orderStatusClick">
<TabPane v-for="(item,index) in orderStatusWithCount" :key="index" :label="item.title" :name="item.value">
</TabPane>
</Tabs>
<t-tabs v-model="currentStatus" @change="orderStatusClick">
<t-tab-panel v-for="(item,index) in orderStatusWithCount" :key="index" :label="item.title" :value="item.value" />
</t-tabs>
</div>
<div class="export">
<Button type="primary" class="mr_10" @click="expressOrderDeliver">批量发货</Button>
<Button @click="exportOrder" type="info" class="export">导出订单</Button>
<Poptip @keydown.enter.native="orderVerification" placement="bottom-start" width="400">
<Button class="export">
核验订单
</Button>
<div class="api" slot="content">
<h2>核验码</h2>
<div style="margin:10px 0;">
<Input v-model="orderCode" style="width:300px; margin-right:10px;" />
<Button style="primary" @click="orderVerification">核验</Button>
<t-button theme="primary" class="mr_10" @click="expressOrderDeliver">批量发货</t-button>
<t-button variant="outline" class="export" @click="exportOrder">导出订单</t-button>
<t-button class="export" @click="verificationVisible = true">核验订单</t-button>
</div>
<t-table :loading="loading" :columns="tColumns" :data="data" rowKey="sn" class="mt_10" />
<div class="mt_10" style="display: flex; justify-content: flex-end">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" :pageSizeOptions="[20, 50, 100]" size="small" :showJumper="true" @change="onPaginationChange" />
</div>
</Poptip>
</t-card>
<t-dialog :visible="verificationVisible" header="核验订单" :width="420" :closeOnOverlayClick="false" @close="verificationVisible=false">
<div style="margin:10px 0; display:flex; align-items:center; justify-content:flex-start">
<t-input v-model="orderCode" style="width:260px; margin-right:10px" />
<t-button theme="primary" @click="orderVerification">核验</t-button>
</div>
<Table
:loading="loading"
:columns="columns"
:data="data"
ref="table"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</t-dialog>
</div>
</template>
@@ -149,6 +85,8 @@ export default {
orderType: "NORMAL",
},
selectDate: null,
verificationVisible: false,
orderCode: '',
columns: [
{
title: "订单号",
@@ -359,6 +297,18 @@ export default {
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const renderFn = nc.render
nc.cell = (h, { row, col, rowIndex }) => renderFn(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
},
// 新增:带数量的订单状态选项
orderStatusWithCount() {
return [
@@ -367,7 +317,7 @@ export default {
{title: `已付款${this.orderNumData.waitDeliveryNum ? '(' + this.orderNumData.waitDeliveryNum + ')' : ''}`, value: 'PAID'},
{title: `待发货${this.orderNumData.waitShipNum ? '(' + this.orderNumData.waitShipNum + ')' : ''}`, value: 'UNDELIVERED'},
{title: `部分发货${this.orderNumData.partsDeliveredNumNum ? '(' + this.orderNumData.partsDeliveredNumNum + ')' : ''}`, value: 'PARTS_DELIVERED'},
{title: `已发${this.orderNumData.deliveredNum ? '(' + this.orderNumData.deliveredNum + ')' : ''}`, value: 'DELIVERED'},
{title: `待收${this.orderNumData.deliveredNum ? '(' + this.orderNumData.deliveredNum + ')' : ''}`, value: 'DELIVERED'},
{title: `待核验${this.orderNumData.waitCheckNum ? '(' + this.orderNumData.waitCheckNum + ')' : ''}`, value: 'TAKE'},
{title: `待自提${this.orderNumData.waitSelfPickNum ? '(' + this.orderNumData.waitSelfPickNum + ')' : ''}`, value: 'STAY_PICKED_UP'},
{title: `已完成${this.orderNumData.finishNum ? '(' + this.orderNumData.finishNum + ')' : ''}`, value: 'COMPLETED'},
@@ -407,11 +357,19 @@ export default {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
onPaginationChange(info) {
if (info && typeof info.pageSize !== 'undefined' && info.pageSize !== this.searchForm.pageSize) {
this.changePageSize(info.pageSize)
}
if (info && typeof info.current !== 'undefined') {
this.changePage(info.current)
}
},
// 搜索订单
handleSearch() {
this.searchForm.pageNumber = 1;
@@ -421,15 +379,26 @@ export default {
},
// 重置
handleReset() {
this.searchForm = {};
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.selectDate = null;
this.searchForm.startDate = "";
this.searchForm.endDate = "";
this.searchForm.orderType = "NORMAL",
// 重新加载数据
this.getDataList();
this.searchForm = {
pageNumber: 1,
pageSize: 20,
sort: 'createTime',
order: 'desc',
startDate: '',
endDate: '',
orderType: '',
orderSn: '',
keywords: '',
buyerName: '',
goodsName: '',
shipName: '',
orderStatus: '',
paymentMethod: '',
}
this.selectDate = null
this.currentStatus = ''
this.getDataList()
this.getOrderNumData()
},
// 起始时间处理
selectDateRange(v) {
@@ -491,17 +460,10 @@ export default {
},
// 订单筛选
orderStatusClick(name) {
if (name === 0) {
// 点击"全部"时设置为空字符串在getDataList中会被过滤掉
this.searchForm.orderStatus = '';
} else {
// 其他状态正常赋值
this.searchForm.orderStatus = name;
}
this.currentStatus = name;
this.getDataList();
orderStatusClick(value) {
this.searchForm.orderStatus = value || ''
this.currentStatus = value
this.getDataList()
},
getOrderNumData() {
// 创建一个不包含orderStatus字段的搜索参数
@@ -534,7 +496,7 @@ export default {
}
// Tab组件样式
.order-tab {
::v-deep .ivu-tabs-tab {
::v-deep .t-tabs__nav-item {
font-size: 14px;
}
}

View File

@@ -208,14 +208,14 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.searchForm = {};
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.searchForm.orderType = "VIRTUAL";
this.selectDate = null;
this.searchForm.startDate = "";

View File

@@ -29,7 +29,7 @@
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small"
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small"
show-total show-elevator show-sizer></Page>
</Row>
</Card>
@@ -47,7 +47,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
receiptStatus: "", // 发票状态
@@ -202,14 +202,14 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getData();
},
// 重置搜索条件
handleReset() {
this.searchForm = {};
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getData();
},
// 时间段从新赋值

View File

@@ -0,0 +1,84 @@
<template>
<div class="info">
<t-card>
<t-descriptions title="优惠券详情" column="2" bordered>
<t-descriptions-item label="活动名称">{{ info.promotionName }}</t-descriptions-item>
<t-descriptions-item label="优惠券名称">{{ info.couponName }}</t-descriptions-item>
<t-descriptions-item label="类型">{{ couponTypeText }}</t-descriptions-item>
<t-descriptions-item label="金额/折扣">
<div v-if="info.couponType === 'PRICE'"><priceColorScheme :value="info.price" :color="$mainColor" /></div>
<div v-else>{{ (info.couponDiscount || 0) + '' }}</div>
</t-descriptions-item>
<t-descriptions-item label="活动方式">{{ getTypeText }}</t-descriptions-item>
<t-descriptions-item label="发放数量">{{ info.publishNum === 0 ? '不限制' : info.publishNum }}</t-descriptions-item>
<t-descriptions-item label="领取限制">{{ info.couponLimitNum === 0 ? '不限制' : info.couponLimitNum }}</t-descriptions-item>
<t-descriptions-item label="消费门槛">{{ info.consumeThreshold }}</t-descriptions-item>
<t-descriptions-item label="有效期">
<span v-if="info.getType === 'ACTIVITY' && info.rangeDayType === 'DYNAMICTIME'">长期有效</span>
<span v-else-if="info.startTime && info.endTime"><div v-html="info.startTime + '<br/>' + info.endTime"></div></span>
</t-descriptions-item>
<t-descriptions-item label="使用范围">{{ scopeTypeText }}</t-descriptions-item>
<t-descriptions-item label="范围描述">{{ info.description }}</t-descriptions-item>
</t-descriptions>
<div v-if="info.scopeType === 'PORTION_GOODS' && info.promotionGoodsList && info.promotionGoodsList.length" class="mt_10">
<t-table :columns="goodsColumns" :data="info.promotionGoodsList" rowKey="skuId"></t-table>
</div>
<div class="mt_10">
<t-button theme="primary" @click="back">返回</t-button>
</div>
</t-card>
</div>
</template>
<script>
import { getShopCoupon } from "@/api/promotion";
export default {
name: "coupon-info",
data() {
return {
info: {},
goodsColumns: [
{ title: "商品名称", colKey: "goodsName", minWidth: 120 },
{ title: "商品价格", colKey: "price", minWidth: 80, cell: (h, { row }) => h('priceColorScheme', { props: { value: row.price, color: this.$mainColor } }) },
{ title: "库存", colKey: "quantity", minWidth: 80 }
]
};
},
computed: {
couponTypeText() {
const t = this.info.couponType;
return t === "DISCOUNT" ? "打折" : t === "PRICE" ? "减免现金" : "";
},
getTypeText() {
const t = this.info.getType;
return t === "FREE" ? "免费领取" : t === "ACTIVITY" ? "活动赠送" : "";
},
scopeTypeText() {
const t = this.info.scopeType;
return t === "ALL" ? "全品类" : t === "PORTION_GOODS" ? "指定商品" : t === "PORTION_GOODS_CATEGORY" ? "部分商品分类" : "";
}
},
methods: {
init() {
const id = this.$route.query.id;
getShopCoupon(id).then((res) => {
if (res && res.success) {
const data = res.result || {};
if (!Array.isArray(data.promotionGoodsList)) data.promotionGoodsList = data.promotionGoodsList || [];
this.info = data;
}
});
},
back() {
this.$router.push({ name: "coupon" });
}
},
mounted() {
this.init();
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";
</style>

View File

@@ -117,7 +117,7 @@
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<div style="display: flex; margin-bottom: 10px">
<div class="flex mb_10">
<Button :disabled="disabled" type="primary" @click="openSkuList"
>选择商品</Button
>
@@ -609,7 +609,7 @@ h4 {
margin-left: 10px;
color: #999;
}
.ivu-form-item {
.t-form__item {
margin-bottom: 24px !important;
}
.wrapper {

View File

@@ -1,12 +1,12 @@
<template>
<div class="search">
<Card>
<Button style="margin-bottom: 10px" @click="back()">返回</Button>
<Button class="mb_10" @click="back()">返回</Button>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="75"
:label-width="100"
class="search-form mb_10"
>
<Form-item label="优惠券名称" prop="couponName">
@@ -46,7 +46,7 @@
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 240px"
style="width: 360px"
></DatePicker>
</Form-item>
<Button
@@ -77,7 +77,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -102,7 +102,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
getType: "", // 默认排序方式
@@ -244,7 +244,7 @@ export default {
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
/**
@@ -282,3 +282,10 @@ export default {
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";
.search-form {
width: 100% !important;
}
</style>

View File

@@ -1,72 +1,63 @@
<template>
<div class="search">
<Card>
<Row>
<Form
<t-card>
<t-form
ref="searchForm"
:model="searchForm"
inline
:label-width="100"
:data="searchForm"
layout="inline"
:labelWidth="100"
class="search-form"
>
<Form-item label="优惠券名称">
<Input
type="text"
<t-form-item label="优惠券名称" name="couponName">
<t-input
v-model="searchForm.couponName"
placeholder="请输入优惠券名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 240px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
</t-form-item>
<t-form-item label="活动时间">
<t-date-range-picker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 240px"
></DatePicker>
</Form-item>
<Button
style="width: 300px"
valueType="time-stamp"
/>
</t-form-item>
<t-form-item>
<t-button
@click="handleSearch"
type="primary"
theme="primary"
class="search-btn"
icon="ios-search"
>搜索</Button
>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Row>
</Card>
<Card>
<Row class="operator padding-row">
<Button @click="add" type="primary">添加</Button>
<Button @click="delAll" class="ml_10">批量关闭</Button>
<Button @click="receivePage()" class="ml_10" type="info">优惠券领取记录</Button>
</Row>
<Table
>搜索</t-button>
<t-button @click="handleReset" class="search-btn" style="margin-left: 8px">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="operator padding-row">
<t-button @click="add" theme="primary">添加</t-button>
<t-button @click="delAll" class="ml_10">批量关闭</t-button>
<t-button @click="receivePage()" class="ml_10" variant="outline">优惠券领取记录</t-button>
</div>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<t-table
class="mt_10"
:loading="loading"
border
:columns="columns"
:columns="tColumns"
:data="data"
ref="table"
@on-selection-change="changeSelect"
rowKey="id"
:rowSelection="{ type: 'multiple', selectedRowKeys }"
@select-change="onSelectChange"
>
<template slot-scope="{ row }" slot="action">
<template #action="{ row }">
<a
v-if="row.promotionStatus === 'NEW' || row.promotionStatus === 'CLOSE'"
style="color:#2d8cf0;cursor:pointer;text-decoration:none"
@@ -92,31 +83,27 @@
@click="receivePage(row.id)"
>领取记录</a>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
</t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:total="Number(total)"
:pageSize="searchForm.pageSize"
:pageSizeOptions="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
showJumper
showPageSize
@change="({ current }) => changePage(current)"
@page-size-change="(size) => changePageSize(size)"
/>
</div>
</t-card>
</div>
</template>
<script>
import { getShopCouponList, updateCouponStatus } from "@/api/promotion";
import {
promotionsStatusRender,
promotionsScopeTypeRender,
} from "@/utils/promotions";
export default {
name: "coupon",
@@ -127,12 +114,14 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
},
selectList: [], // 多选数据
selectCount: 0, // 多选计数
selectedRowKeys: [],
columns: [
// 表头
{
@@ -175,7 +164,7 @@ export default {
},
{
title: "已被使用的数量/已领取数量",
key: "publishNum",
key: "usedCount",
render: (h, params) => {
return h("div", params.row.usedNum + "/" + params.row.receivedNum);
},
@@ -193,14 +182,7 @@ export default {
return h("div", [text]);
},
},
{
title: "品类描述",
key: "scopeType",
width: 120,
render: (h, params) => {
return promotionsScopeTypeRender(h, params);
},
},
{
title: "活动时间",
width: 150,
@@ -226,7 +208,9 @@ export default {
key: "promotionStatus",
fixed: "right",
render: (h, params) => {
return promotionsStatusRender(h, params);
const s = params?.row?.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -241,6 +225,30 @@ export default {
total: 0, // 表单数据总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
init() {
this.getDataList();
@@ -279,7 +287,7 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
};
@@ -287,18 +295,22 @@ export default {
this.getDataList();
},
clearSelectAll() {
this.$refs.table.selectAll(false);
this.selectedRowKeys = [];
this.selectList = [];
this.selectCount = 0;
},
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
onSelectChange(selectedRowKeys, { selectedRowData } = {}) {
this.selectedRowKeys = selectedRowKeys || [];
const rows = selectedRowData || [];
this.selectList = rows;
this.selectCount = rows.length;
},
// 获取列表数据
getDataList() {
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
this.searchForm.startTime = this.selectDate[0];
this.searchForm.endTime = this.selectDate[1];
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
@@ -315,9 +327,11 @@ export default {
},
// 跳转编辑优惠券页面
see(v, only) {
let data;
only ? (data = { onlyView: true, id: v.id }) : (data = { id: v.id });
this.$router.push({ name: "add-coupon", query: data });
if (only) {
this.$router.push({ name: "coupon-info", query: { id: v.id } });
} else {
this.$router.push({ name: "add-coupon", query: { id: v.id } });
}
},
// 下架优惠券
remove(v) {

View File

@@ -11,13 +11,9 @@
</FormItem>
<FormItem label="活动时间" prop="rangeTime">
<DatePicker type="datetimerange" v-model="form.rangeTime" :disabled="form.promotionStatus != 'NEW'"
format="yyyy-MM-dd HH:mm:ss" placeholder="请选择" :options="options" style="width: 280px">
format="yyyy-MM-dd HH:mm:ss" placeholder="请选择" :options="options" style="width: 420px">
</DatePicker>
</FormItem>
<FormItem label="活动描述" prop="description">
<Input v-model="form.description" :disabled="form.promotionStatus != 'NEW'" type="textarea" :rows="4"
clearable style="width: 280px" />
</FormItem>
</div>
<h4>优惠设置</h4>
@@ -82,7 +78,7 @@
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<div style="display: flex; margin-bottom: 10px" v-if="form.promotionStatus == 'NEW'">
<div class="flex mb_10" v-if="form.promotionStatus == 'NEW'">
<Button type="primary" @click="openSkuList">选择商品</Button>
<Button type="error" ghost style="margin-left: 10px" @click="delSelectGoods">批量删除</Button>
</div>
@@ -156,6 +152,7 @@ export default {
Cookies,
form: {
// 活动表单
promotionName: "",
discountType: "fullMinusFlag",
scopeType: "ALL",
promotionGoodsList: [],
@@ -168,7 +165,6 @@ export default {
// 验证规则
promotionName: [{ required: true, message: "活动名称不能为空" }],
rangeTime: [{ required: true, message: "请选择活动时间" }],
description: [{ required: true, message: "请填写活动描述" }],
price: [
{ required: true, message: "请输入面额" },
{ validator: checkPrice },
@@ -236,6 +232,9 @@ export default {
this.getDetail();
this.columns.shift()
this.columns.pop()
} else {
const today = this.$options.filters.unixToDate(Date.now() / 1000, "yyyy-MM-dd");
this.$set(this.form, 'promotionName', `满额活动${today}`);
}
await this.getCouponList();
await this.getGiftList();
@@ -397,7 +396,7 @@ export default {
getCouponList (query) {
// 优惠券列表
let params = {
pageSize: 10,
pageSize: 20,
pageNumber: 0,
getType: "ACTIVITY",
couponName: query,
@@ -414,7 +413,7 @@ export default {
getGiftList (query) {
// 赠品列表
let params = {
pageSize: 10,
pageSize: 20,
pageNumber: 1,
id: query === this.form.giftId ? this.form.giftId : null,
goodsName: query === this.form.giftId ? null : query,
@@ -452,7 +451,7 @@ h4 {
color: #999;
}
.ivu-form-item {
.t-form__item {
margin-bottom: 24px !important;
}
</style>

View File

@@ -5,14 +5,6 @@
<Form-item label="活动名称">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select v-model="searchForm.promotionStatus" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker v-model="selectDate" type="daterange" clearable placeholder="选择起始时间" style="width: 240px">
</DatePicker>
@@ -27,6 +19,13 @@
<Row class="operation">
<Button type="primary" @click="newAct">新增</Button>
</Row>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
@@ -74,6 +73,7 @@ export default {
pageSize: 20,
sort: "startTime",
order: "desc",
promotionStatus: "",
},
columns: [
{
@@ -101,32 +101,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "default";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "blue";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [
h(
"Tag",
{
props: {
color: color,
},
},
text
),
]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -139,6 +116,15 @@ export default {
data: [], // 表格数据
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
// 改变页码
newAct () {
@@ -161,7 +147,7 @@ export default {
// 搜索
handleSearch () {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -173,6 +159,7 @@ export default {
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.getDataList();
},

View File

@@ -526,7 +526,7 @@ export default {
<style lang="scss" scoped>
.action {
display: flex;
::v-deep .ivu-btn {
::v-deep .t-button {
margin: 0 5px !important;
}
}

View File

@@ -1,38 +1,23 @@
<template>
<div>
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="100" class="search-form">
<Form-item label="直播状态" prop="promotionStatus">
<Select v-model="searchForm.status" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">直播中</Option>
<Option value="END">已结束</Option>
</Select>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card>
<t-card>
<div class="btns">
<Button @click="createLive()" type="primary">创建直播</Button>
<t-button theme="primary" @click="createLive()">创建直播</t-button>
</div>
<Tabs v-model="searchForm.status">
<t-tabs v-model="searchForm.status">
<!-- 标签栏 -->
<TabPane v-for="(item,index) in tabs" :key="index" :name="item.status" :label="item.title">
<t-tab-panel v-for="(item,index) in tabs" :key="index" :value="item.status" :label="item.title">
</TabPane>
</t-tab-panel>
</Tabs>
<Table :columns="liveColumns" :data="liveData"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePageNumber" @on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]"
size="small" show-total show-elevator show-sizer></Page>
</Row>
</t-tabs>
<t-table :columns="liveColumns" :data="liveData"></t-table>
<t-row justify="end" class="mt_10">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" @change="(info) => { if (info && typeof info.pageSize !== 'undefined' && info.pageSize !== searchForm.pageSize) { changePageSize(info.pageSize) } if (info && typeof info.current !== 'undefined') { changePageNumber(info.current) } }" :pageSizeOptions="[20, 50, 100]" size="small" :showJumper="true" />
</t-row>
</Card>
</t-card>
</div>
</template>
@@ -47,10 +32,14 @@ export default {
searchForm: {
pageSize: 20,
pageNumber: 1,
status: "NEW",
status: "",
},
// 直播tab选项栏
tabs: [
{
title: "全部",
status: "",
},
{
title: "直播中",
status: "START",
@@ -67,81 +56,26 @@ export default {
liveColumns: [
{
title: "直播标题",
key: "name",
colKey: "name",
},
{
title: "主播昵称",
key: "anchorName",
colKey: "anchorName",
},
{
title: "直播开始时间",
key: "createTime",
render: (h, params) => {
return h(
"span",
this.$options.filters.unixToDate(params.row.startTime)
);
},
},
{
title: "直播结束时间",
key: "endTime",
render: (h, params) => {
return h(
"span",
this.$options.filters.unixToDate(params.row.endTime)
);
},
},
{
title: "直播状态",
render: (h, params) => {
return h(
"span",
params.row.status == "NEW"
? "未开始"
: params.row.status == "START"
? "直播中"
: "已结束"
);
},
title: "开始时间",
colKey: "startTime",
cell: (h, { row }) => h('span', this.$options.filters.unixToDate(row.startTime))
},
{
title: "操作",
key: "action",
render: (h, params) => {
return h(
"div",
{
style: {
display: "flex",
},
},
[
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.getLiveDetail(params.row);
},
},
},
"查看/添加商品"
),
]
);
},
},
], //table中显示的title
colKey: "action",
cell: (h, { row }) => h('a', {
style: { color: '#2d8cf0', cursor: 'pointer', textDecoration: 'none' },
on: { click: () => this.getLiveDetail(row) }
}, '查看/添加商品')
}
],
liveData: [], //table中显示的直播数据
};
},
@@ -149,6 +83,7 @@ export default {
"searchForm.status": {
handler() {
this.liveData = [];
this.searchForm.pageNumber = 1;
this.getStoreLives();
},
deep: true,

View File

@@ -1,59 +1,59 @@
<template>
<div class="wrapper">
<Card>
<Form ref="searchForm" :model="params" inline :label-width="100" class="search-form">
<Form-item label="商品名称">
<Input type="text" v-model="params.name" placeholder="请输入商品名称" clearable style="width: 240px" />
</Form-item>
<t-card>
<t-form ref="searchForm" :data="params" layout="inline" :labelWidth="100" class="search-form">
<t-form-item label="商品名称" name="name">
<t-input v-model="params.name" placeholder="请输入商品名称" clearable style="width: 240px" />
</t-form-item>
<Button @click="getLiveGoodsMethods('clear')" type="primary" class="search-btn" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card>
<t-form-item>
<t-button @click="getLiveGoodsMethods('clear')" theme="primary" class="search-btn">搜索</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<h4 v-if="!reviewed">
由于直播商品需经过小程序直播平台的审核你需要在此先提审商品为了不影响直播间选取商品请提前1天提审商品
</h4>
<div>
<Tabs v-model="params.auditStatus">
<TabPane v-for="(item,index) in liveTabWay" :key="index" :label="item.label" :name="item.type+''">
</TabPane>
</Tabs>
<t-tabs :value="params.auditStatus" @change="val => params.auditStatus = Number(val)">
<t-tab-panel v-for="(item,index) in liveTabWay" :key="index" :label="item.label" :value="item.type">
</t-tab-panel>
</t-tabs>
</div>
<Button v-if="!reviewed" type="primary" style="margin-bottom:10px;" @click="addNewLiveGoods" icon="md-add">选择商品</Button>
<Button type="primary" v-if="params.auditStatus == 0" ghost style="margin:0 0 10px 10px" @click="getLiveGoodsMethods('clear')">更新状态</Button>
<t-button v-if="!reviewed" theme="primary" class="mb_10" @click="addNewLiveGoods">选择商品</t-button>
<t-button theme="primary" v-if="params.auditStatus == 0" variant="outline" style="margin:0 0 10px 10px" @click="getLiveGoodsMethods('clear')">更新状态</t-button>
<div style="position:relative">
<Spin size="large" fix v-if="tableLoading">
</Spin>
<Table class="mt_10" disabled-hover :columns="liveGoodsColumns" :data="liveGoodsData">
<t-table class="mt_10" :columns="tColumns" :data="liveGoodsData" rowKey="id">
<template slot-scope="{ row }" slot="goodsName">
<template #goodsName="{ row }">
<div class="flex-goods">
<img class="thumbnail" :src="row.thumbnail || row.goodsImage">
{{ row.goodsName || row.name }}
</div>
</template>
<template slot-scope="{ row ,index }" class="price" slot="price">
<template #price="{ row ,index }">
<!-- 如果为新增商品显示 -->
<RadioGroup v-if="params.auditStatus == 99" @on-change="changeRadio(row,'priceType')" v-model="row.priceType">
<t-radio-group v-if="params.auditStatus == 99" @change="val => changeRadio(row,'priceType', val)" v-model="row.priceType">
<div class="price-item">
<Radio :label="1">一口价:</Radio>
<InputNumber :min="0.1" v-if="liveGoodsData[index].priceType == 1" style="width:100px" v-model="liveGoodsData[index].price"></InputNumber>
<t-radio :value="1">一口价:</t-radio>
<t-input-number :min="0.1" v-if="liveGoodsData[index].priceType == 1" style="width:100px" v-model="liveGoodsData[index].price"></t-input-number>
</div>
<div class="price-item">
<Radio :label="2">区间价:</Radio> <span v-if="liveGoodsData[index].priceType == 2">
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price" />
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
<t-radio :value="2">区间价:</t-radio> <span v-if="liveGoodsData[index].priceType == 2">
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price" />
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
</span>
</div>
<div class="price-item">
<Radio :label="3">折扣价:</Radio> <span v-if="liveGoodsData[index].priceType == 3">原价<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price"></InputNumber>现价
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
<t-radio :value="3">折扣价:</t-radio> <span v-if="liveGoodsData[index].priceType == 3">原价<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price"></t-input-number>现价
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
</span>
</div>
</RadioGroup>
</t-radio-group>
<div v-else>
<div v-if="row.priceType == 1"><priceColorScheme :value="row.price" :color="$mainColor" /></div>
<div class="flex" v-if="row.priceType == 2"><priceColorScheme :value="row.price" :color="$mainColor" />至<priceColorScheme :value="row.price2" :color="$mainColor" /></div>
@@ -62,25 +62,23 @@
</template>
<template slot-scope="{ row ,index }" slot="action">
<template #action="{ row ,index }">
<a v-if="params.auditStatus == 99" @click="liveGoodsData.splice(index,1)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">删除</a>
<span v-if="params.auditStatus == 99 || (params.auditStatus != 99 && !reviewed) || reviewed" style="margin:0 8px;color:#dcdee2">|</span>
<a v-if="params.auditStatus != 99 && !reviewed" @click="$router.push({path:'/goods-operation-edit',query:{id:row.goodsId}})" style="color:#2d8cf0;cursor:pointer;text-decoration:none">查看</a>
<span v-if="reviewed" style="margin:0 8px;color:#dcdee2">|</span>
<a v-if="reviewed" @click="selectedLiveGoods(row,index)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">{{row.___selected ? '':''}}选择</a>
</template>
</Table>
</t-table>
<div class="flex">
<Page size="small" :total="goodsTotal" @on-change="changePageNumber" class="pageration" @on-page-size-change="changePageSize" :page-size="params.pageSize" show-total show-elevator
show-sizer>
</Page>
<t-pagination size="small" :total="Number(goodsTotal)" @change="({ current }) => changePageNumber(current)" class="pageration" @page-size-change="(size) => changePageSize(size)" :pageSize="params.pageSize" :pageSizeOptions="[20, 50, 100]" showJumper showPageSize />
</div>
</div>
</Card>
</t-card>
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
<div v-if="params.auditStatus == 99" class="submit">
<Button type="primary" :loading="saveGoodsLoading" @click="saveLiveGoods">保存商品</Button>
<t-button theme="primary" :loading="saveGoodsLoading" @click="saveLiveGoods">保存商品</t-button>
</div>
</div>
</template>
@@ -99,7 +97,7 @@ export default {
tableLoading: false, //表格是否加载
params: {
pageNumber: 1,
pageSize: 10,
pageSize: 20,
auditStatus: 2, //商品状态
},
// 商品审核状态
@@ -152,6 +150,16 @@ export default {
selectedGoods: [],
};
},
computed: {
tColumns() {
return (this.liveGoodsColumns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
return nc
})
}
},
props: {
// 是否是已审核,此处为组件模式时使用。去除添加等功能 只保留查询以及新增选择回调数据
reviewed: {

View File

@@ -181,7 +181,7 @@ export default {
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-form-item {
::v-deep .t-form__item {
padding: 18px 10px !important;
}
</style>

View File

@@ -49,7 +49,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -89,7 +89,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
},
submitLoading: false, // 添加或编辑提交状态
@@ -230,7 +230,7 @@ export default {
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},

View File

@@ -18,19 +18,6 @@
style="width: 240px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 240px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
@@ -55,6 +42,13 @@
<Row class="operation padding-row">
<Button @click="newAct" type="primary">添加</Button>
</Row>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="action">
<div class="row">
@@ -77,7 +71,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -98,9 +92,10 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 0, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
},
selectDate: null, // 选择的时间
columns: [
@@ -122,22 +117,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "default";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "blue";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [h("Tag", { props: { color: color } }, text)]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -151,6 +133,15 @@ export default {
total: 0, // 表单数据总数
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 0
this.getDataList()
},
deep: true
}
},
methods: {
// 初始化数据
init() {
@@ -169,7 +160,7 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 0;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -177,9 +168,10 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 0, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.selectDate = "";

View File

@@ -5,14 +5,6 @@
<Form-item label="活动名称" prop="goodsName">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select v-model="searchForm.promotionStatus" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker v-model="selectDate" type="daterange" clearable placeholder="选择起始时间" style="width: 240px">
</DatePicker>
@@ -22,6 +14,13 @@
</Form>
</Card>
<Card>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" class="mt_10">
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
@@ -38,7 +37,7 @@
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage"
@on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small" show-total show-elevator
@on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small" show-total show-elevator
show-sizer></Page>
</Row>
</Card>
@@ -57,9 +56,10 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
},
columns: [
{
@@ -84,32 +84,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "geekblue";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "volcano";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [
h(
"Tag",
{
props: {
color: color,
},
},
text
),
]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -123,6 +100,15 @@ export default {
total: 0, // 表单数据总数
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
// 初始化数据
init () {
@@ -141,7 +127,7 @@ export default {
// 搜索
handleSearch () {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -149,9 +135,10 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.selectDate = "";
this.getDataList();

View File

@@ -177,14 +177,14 @@
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.searchForm = {}
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取列表数据
@@ -224,7 +224,7 @@
<style lang="scss" scoped>
// 建议引入通用样式 可删除下面样式代码
@import "@/styles/table-common.scss";
::v-deep .ivu-col{
::v-deep .t-col{
min-height: 100vh;
}
</style>

View File

@@ -48,7 +48,7 @@
<Row type="flex" justify="end" class="mt_10">
<Page :current="orderParam.pageNumber" :total="orderTotal" :page-size="orderParam.pageSize"
@on-change="orderChangePage" @on-page-size-change="orderChangePageSize" size="small" show-total
show-elevator></Page>
show-elevator show-sizer :page-size-opts="[20, 50, 100]"></Page>
</Row>
</Tab-pane>
</Tabs>
@@ -277,7 +277,7 @@ export default {
bill: {}, // 商家信息
orderParam: {
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "id", // 默认排序字段
order: "desc", // 默认排序方式

View File

@@ -54,7 +54,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -76,7 +76,7 @@
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
@@ -182,14 +182,14 @@
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.searchForm = {}
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取列表数据

View File

@@ -53,7 +53,7 @@
show-total
:total="total"
show-sizer
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
show-elevator
style="float: right; overflow: hidden"
@on-change="changePageNum"
@@ -97,7 +97,7 @@ export default {
},
searchForm: {
pageNumber: 1,
pageSize: 10,
pageSize: 20,
sort: "createTime",
order: "desc",
pageClientType: "PC",

View File

@@ -57,11 +57,11 @@ export default {
};
</script>
<style scoped lang="scss">
::v-deep .ivu-modal {
::v-deep .t-dialog {
overflow: hidden;
height: 650px !important;
}
::v-deep .ivu-modal-body {
::v-deep .t-dialog__body {
width: 100%;
height: 500px;
overflow: hidden;

View File

@@ -353,7 +353,7 @@ export default {
.search {
width: 460px;
margin: 0 auto;
::v-deep .ivu-input.ivu-input-large {
::v-deep .t-input.t-size-l {
border: 2px solid $theme_color;
font-size: 12px;
height: 34px;
@@ -361,7 +361,7 @@ export default {
box-shadow: none;
}
}
::v-deep .ivu-input-group-append {
::v-deep .t-input-adornment .t-input-adornment__append {
border: 1px solid $theme_color;
border-left: none;
height: 30px;

View File

@@ -433,7 +433,7 @@ export default {
height: inherit;
font-size: 12px;
font-weight: bold;
.ivu-icon {
.t-icon {
position: absolute;
right: 10px;
top: 10px;
@@ -457,14 +457,14 @@ export default {
align-items: center;
flex-direction: column;
justify-content: center;
.ivu-icon {
.t-icon {
font-size: 18px;
transition: all 0.3s ease-out;
}
&:hover {
background-color: $theme_color;
color: #fff;
.ivu-icon {
.t-icon {
transform: rotateZ(360deg);
}
}

View File

@@ -241,7 +241,7 @@ export default {
margin-top: 10px;
}
.ivu-btn-default {
.t-button[variant="outline"], .t-button[variant="dashed"], .t-button {
color: $theme_color;
border-color: $theme_color;
}

View File

@@ -319,7 +319,7 @@ export default {
margin-top: 10px;
}
.ivu-btn-default {
.t-button[variant="outline"], .t-button[variant="dashed"], .t-button {
color: $theme_color;
border-color: $theme_color;
}

View File

@@ -16,7 +16,7 @@
z-index: 99;
width: 100%;
height: 100%;
.ivu-btn{
.t-button{
float: right;
margin-right: 5px;
margin-top: 5px;
@@ -56,7 +56,7 @@
>*{
margin-bottom: 10px;
}
.ivu-input-wrapper{
.t-input{
width: 200px;
}
}

View File

@@ -35,7 +35,7 @@
cursor: pointer;
.ivu-card-body {
.t-card__body {
padding: 0;
}
@@ -228,7 +228,7 @@
}
/* Checkbox默认的样式 */
.check-box {
.ivu-checkbox {
.t-checkbox {
position: absolute;
right: 10px;
top: 10px;
@@ -236,27 +236,27 @@
}
}
/* 覆盖iView默认的Checkbox样式 */
.ivu-checkbox-wrapper {
.t-checkbox {
/*font-size: 16px; !* 修改字体大小 *!*/
/*color: #495060; !* 修改文本颜色 *!*/
/* 添加其他需要的样式 */
}
.ivu-checkbox-inner {
.t-checkbox__input {
/*width: 20px; !* 修改选框大小 *!*/
/*height: 20px;*/
/*border-color: #dcdee2; !* 修改边框颜色 *!*/
/* 添加其他需要的样式 */
}
/* 当Checkbox被选中时的样式 */
.ivu-checkbox-checked .ivu-checkbox-inner {
.t-is-checked .t-checkbox__input {
/*background-color: #2db7f5; !* 修改选中时的背景颜色 *!*/
}
/* 当Checkbox不可用时的样式 */
.ivu-checkbox-disabled .ivu-checkbox-inner {
.t-is-disabled .t-checkbox__input {
/*background-color: #e9e9e9; !* 修改禁用状态下的背景颜色 *!*/
}
.demo-tree-render .ivu-tree-title{
.demo-tree-render .t-tree__label{
width: 94%;
}
}

View File

@@ -20,7 +20,7 @@
.table {
flex: 11;
}
.ivu-card {
.t-card {
width: 100%;
}
.modal-footer {
@@ -72,7 +72,7 @@
<Col :span="isComponent?5:4">
<div class="file-list">
<div class="article-category mr_10">
<Tree :data="treeData" :render="renderContent" @on-select-change.self="handleCateChange" class="demo-tree-render"></Tree>
<Tree :data="treeData" :render="renderContent" @on-select-change="handleCateChange" class="demo-tree-render"></Tree>
<div class="group-row flex" v-if="!isComponent">
<Button @click="handleClickAddGroup">添加分组</Button>
</div>
@@ -143,7 +143,7 @@
</CheckboxGroup>
</div>
<div class="page-box">
<Page :total="total" :page-size="searchForm.pageSize" show-elevator @on-change="pageChange" size="small" />
<Page :total="total" :page-size="searchForm.pageSize" show-elevator show-sizer :page-size-opts="[20, 50, 100]" @on-change="pageChange" size="small" />
</div>
</div>
</Col>
@@ -900,24 +900,22 @@
this.searchForm.pageNumber = value;
this.getDataList();
},
// 自定义tree节点显示内容和交互
renderContent (h, { root, node, data }) {
return h('span', {style: {display: 'inline-block', width: '100%'}},
[
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}},
[
h("Dropdown", {style: {marginLeft: "4px"}},
[
h("Icon", {props: {type: 'ios-more', size: "20",}, style: {display: 'inline-block'}, on:{click: () => {}}}),
h("DropdownMenu", {slot: "list"
}, [
h("DropdownItem", { nativeOn:{click: () => {this.handleContextMenuEdit()}} }, "编辑"),
h("DropdownItem", { nativeOn:{click: () => {this.handleContextMenuDelete()}} }, "删除"),
renderContent(h, ctx) {
const node = (ctx && ctx.node) || null
const data = (ctx && ctx.data) || (node && node.data) || {}
const titleVNode = h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)])
return h('span', { style: { display: 'inline-block', width: '100%' } }, [
titleVNode,
h('span', { style: { display: 'inline-block', float: 'right', marginRight: '10px' } }, [
h('Dropdown', { style: { marginLeft: '4px' } }, [
h('Icon', { props: { type: 'ios-more', size: '20' }, style: { display: 'inline-block' } }),
h('DropdownMenu', { slot: 'list' }, [
h('DropdownItem', { nativeOn: { click: () => { this.handleContextMenuEdit() } } }, '编辑'),
h('DropdownItem', { nativeOn: { click: () => { this.handleContextMenuDelete() } } }, '删除')
])
])
])
]),
])
]);
},
@@ -1158,20 +1156,12 @@
// 改变查看方式
changeShowType() {
this.searchForm.pageNumber = 1;
if (this.showType == "list") {
this.searchForm.pageSize = 10;
} else {
this.searchForm.pageSize = 12;
}
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取列表数据
getDataList(type = null) {
if (this.showType == "list") {
this.pageSizeOpts = [10, 20, 50];
} else {
this.pageSizeOpts = [12, 24, 48];
}
this.pageSizeOpts = [20, 50, 100];
this.loading = true;
getFileListData(this.searchForm).then((res) => {
this.loading = false;
@@ -1187,11 +1177,7 @@
handleSearch() {
this.searchForm.title = this.searchForm.name;
this.searchForm.pageNumber = 1;
if (this.showType == "list") {
this.searchForm.pageSize = 5;
} else {
this.searchForm.pageSize = 12;
}
this.searchForm.pageSize = 20;
this.getDataList();
},
// 文件类型筛选

View File

@@ -93,7 +93,7 @@
</CheckboxGroup>
</div>
<div class="page-box">
<Page :total="total" :page-size="searchForm.pageSize" show-elevator @on-change="pageChange" size="small" />
<Page :total="total" :page-size="searchForm.pageSize" show-elevator show-sizer :page-size-opts="[20, 50, 100]" @on-change="pageChange" size="small" />
</div>
</div>
</Col>
@@ -959,20 +959,12 @@
// 改变查看方式
changeShowType() {
this.searchForm.pageNumber = 1;
if (this.showType == "list") {
this.searchForm.pageSize = 10;
} else {
this.searchForm.pageSize = 12;
}
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取列表数据
getDataList(type = null) {
if (this.showType == "list") {
this.pageSizeOpts = [10, 20, 50];
} else {
this.pageSizeOpts = [12, 24, 48];
}
this.pageSizeOpts = [20, 50, 100];
this.loading = true;
getFileListData(this.searchForm).then((res) => {
this.loading = false;
@@ -988,11 +980,7 @@
handleSearch() {
this.searchForm.title = this.searchForm.name;
this.searchForm.pageNumber = 1;
if (this.showType == "list") {
this.searchForm.pageSize = 5;
} else {
this.searchForm.pageSize = 12;
}
this.searchForm.pageSize = 20;
this.getDataList();
},
// 文件类型筛选

View File

@@ -1,7 +1,7 @@
<template>
<div class="logistics">
<t-card>
<t-table :loading="loading" :columns="columns" :data="data">
<t-table :loading="loading" :columns="columns" :data="data" rowKey="logisticsId">
<template #selected="{ row }">
<t-tag :theme="row.selected ? 'success' : 'danger'">{{ row.selected ? '开启' : '关闭' }}</t-tag>
</template>
@@ -16,13 +16,13 @@
</t-table>
</t-card>
<t-dialog :visible="openModal" :header="openModalTitle" :width="700" @close="cancelModal">
<h3 style="color: #ff3c2a; margin-bottom: 10px">是否需要电子面单</h3>
<div style="margin-bottom: 10px;">
<h3 class="mb_10" style="color: #ff3c2a">是否需要电子面单</h3>
<div class="mb_10">
<t-button :theme="faceSheetForm.faceSheetFlag ? 'primary' : 'default'" @click="faceSheetForm.faceSheetFlag = true">需要</t-button>
<t-button :theme="!faceSheetForm.faceSheetFlag ? 'primary' : 'default'" @click="faceSheetForm.faceSheetFlag = false" style="margin-left:8px">不需要</t-button>
</div>
<t-card v-if="openText" class="modalStyle">
<h3 style="color: #ff3c2a; margin-bottom: 10px">请输入详细信息</h3>
<h3 class="mb_10" style="color: #ff3c2a">请输入详细信息</h3>
<t-form ref="formValidate" :data="faceSheetForm" :labelWidth="250">
<t-form-item label="电子面单客户账户/月结账号/客户代码" name="customerName">
<t-input v-model="faceSheetForm.customerName" class="faceSheetInput" />
@@ -78,7 +78,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
},

View File

@@ -183,10 +183,10 @@ export default {
index:'0',
selectedIndex: 0, //选中的地址模板下标
item: "", //运费模板子模板
shipInfo: {}, // 运费模板数据
shipInfo: [], // 运费模板数据
title: "添加运费模板", // 模态框标题
operation: "add", // 操作状态
currentTab: "", // 当前模板tab
operation: "INFO", // 操作状态
currentTab: "INFO", // 当前模板tab
// submitLoading:false,
saveError: false, // 是否显示错误提示
csTab: false, // 添加运费模板显示
@@ -222,6 +222,9 @@ export default {
methods: {
// 初始化数据
init() {
this.currentTab = 'INFO';
this.operation = 'INFO';
this.csTab = false;
this.getData();
},
//切换tabPane

View File

@@ -17,7 +17,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -76,7 +76,7 @@
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
},
form: {
// 添加或编辑表单对象初始化数据
@@ -212,14 +212,14 @@
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
handleReset() {
this.$refs.searchForm.resetFields();
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
//获取地址

View File

@@ -1,6 +1,6 @@
<template>
<div class="search">
<Card style="margin-left: 10px">
<Card class="ml_10">
<Tabs v-model="type" @on-click="handleClickType">
<TabPane label="基本信息" name="INFO">
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
@@ -9,7 +9,7 @@
</FormItem>
<FormItem label="店铺地址" prop="storeAddressPath">
<span>{{ form.storeAddressPath }}</span>
<Button style="margin-left: 10px;" @click="handleChangeAddress('storeAddress')">选择</Button>
<Button class="ml_10" @click="handleChangeAddress('storeAddress')">选择</Button>
</FormItem>
<FormItem label="详细地址" prop="shopAddressDetail">
<Input v-model="form.storeAddressDetail" clearable style="width: 20%" maxlength="50" />

View File

@@ -1,158 +1,98 @@
<template>
<div class="search">
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="店员名称">
<Input
type="text"
v-model="searchForm.clerkName"
placeholder="请输入店员名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="联系方式">
<Input
type="text"
v-model="searchForm.mobile"
placeholder="请输入联系方式"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="部门">
<t-card>
<t-form ref="searchForm" :data="searchForm" layout="inline" :labelWidth="70" class="search-form">
<t-form-item label="店员名称" name="clerkName">
<t-input v-model="searchForm.clerkName" placeholder="请输入店员名称" clearable style="width: 240px" />
</t-form-item>
<t-form-item label="联系方式" name="mobile">
<t-input v-model="searchForm.mobile" placeholder="请输入联系方式" clearable style="width: 240px" />
</t-form-item>
<t-form-item label="部门">
<department-choose @on-change="handleSelectDep" style="width: 150px;" ref="dep"></department-choose>
</Form-item>
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
</Form>
</Card>
<Card>
<Row class="operation padding-row">
<Button @click="add" type="primary">添加</Button>
<Button @click="delAll">批量删除</Button>
<Button @click="resetPass">重置密码</Button>
</Row>
<br>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
sortable="custom"
@on-sort-change="changeSort"
@on-selection-change="showSelect"
ref="table"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10,20,50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</t-form-item>
<t-form-item>
<t-button theme="primary" class="search-btn" @click="handleSearch">搜索</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="operation padding-row">
<t-button theme="primary" @click="add">添加</t-button>
<t-button @click="delAll">批量删除</t-button>
<t-button @click="resetPass">重置密码</t-button>
</div>
<t-table :loading="loading" :columns="tColumns" :data="data" rowKey="id" :sort="{ sortBy: searchForm.sort, descending: searchForm.order === 'desc' }" @sort-change="changeSort" :rowSelection="{ type: 'multiple', selectedRowKeys }" @select-change="onSelectChange" class="mt_10" />
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" :pageSizeOptions="[20, 50, 100]" size="small" showJumper showPageSize @change="({ current }) => changePage(current)" @page-size-change="(size) => changePageSize(size)" />
</div>
</t-card>
<Modal
:title="modalTitle"
v-model="userEditModalVisible"
:mask-closable="false"
:width="500"
:styles="{top: '30px'}"
>
<Form ref="form" :model="editForm" :label-width="80" :rules="formValidate">
<FormItem label="手机号">
<Input v-model="mobile" disabled/>
</FormItem>
<FormItem label="店员名称">
<Input v-model="clerkName" disabled/>
</FormItem>
<FormItem label="超级管理员" prop="isSuper">
<RadioGroup type="button" button-style="solid" v-model="editForm.isSuper">
<Radio :label="1">
<span></span>
</Radio>
<Radio :label="0">
<span></span>
</Radio>
</RadioGroup>
</FormItem>
<FormItem label="角色" prop="roles" v-if="editForm.isSuper == 0">
<Select v-model="editForm.roles" multiple>
<Option v-for="item in roleList" :value="item.id" :key="item.id" :label="item.name">
</Option>
</Select>
</FormItem>
<Form-item label="所属部门">
<t-dialog :header="modalTitle" :visible="userEditModalVisible" :width="500" :closeOnOverlayClick="false" @close="userEditModalVisible = false">
<t-form ref="form" :data="editForm" :labelWidth="80" :rules="formValidate">
<t-form-item label="手机号">
<t-input v-model="mobile" disabled />
</t-form-item>
<t-form-item label="店员名称">
<t-input v-model="clerkName" disabled />
</t-form-item>
<t-form-item label="超级管理员" name="isSuper">
<t-radio-group v-model="editForm.isSuper">
<t-radio :value="1">是</t-radio>
<t-radio :value="0">否</t-radio>
</t-radio-group>
</t-form-item>
<t-form-item label="角色" name="roles" v-if="editForm.isSuper == 0">
<t-select v-model="editForm.roles" multiple>
<t-option v-for="item in roleList" :key="item.id" :value="item.id" :label="item.name" />
</t-select>
</t-form-item>
<t-form-item label="所属部门">
<department-tree-choose @on-change="handleEditSelectDepTree" ref="depTree"></department-tree-choose>
</Form-item>
</t-form-item>
</t-form>
<template #footer>
<t-button variant="text" @click="userEditModalVisible = false">取消</t-button>
<t-button theme="primary" :loading="submitLoading" @click="updateSubmit">提交</t-button>
</template>
</t-dialog>
</Form>
<div slot="footer">
<Button type="text" @click="userEditModalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="updateSubmit">提交</Button>
</div>
</Modal>
<Modal
:title="modalTitle"
v-model="userModalVisible"
:mask-closable="false"
:width="500"
:styles="{top: '30px'}"
>
<Form ref="form" :model="form" :label-width="80" :rules="formValidate">
<FormItem label="手机号" prop="mobile">
<Input placeholder="请输入要添加的会员手机号码" maxlength="11" style="width: 75%" v-model="form.mobile"
autocomplete="off" @on-change="checkClerks"/>
&nbsp;<Button v-if="!memberCheck" @click="checkClerk">校验</Button>
<Button v-if="memberCheck" @click="checkAgainClerk">重新校验</Button>
</FormItem>
<FormItem v-if="newMember" label="用户名" prop="username">
<Input v-model="form.username" autocomplete="off"/>
</FormItem>
<FormItem v-if="oldMember" label="用户名" prop="username">
<Input v-model="form.username" autocomplete="off" disabled/>
</FormItem>
<FormItem label="密码" prop="password" v-if="newMember" :error="errorPass">
<Input type="password" password v-model="form.password" autocomplete="off"/>
</FormItem>
<FormItem label="超级管理员" prop="isSuper" v-if="newMember || oldMember">
<RadioGroup type="button" button-style="solid" v-model="form.isSuper">
<Radio :label="1">
<span></span>
</Radio>
<Radio :label="0">
<span></span>
</Radio>
</RadioGroup>
</FormItem>
<FormItem label="角色" prop="roles" v-if="(oldMember || newMember) && form.isSuper == 0">
<Select v-model="form.roles" multiple>
<Option v-for="item in roleList" :value="item.id" :key="item.id" :label="item.name">
</Option>
</Select>
</FormItem>
<Form-item label="所属部门" v-if="oldMember || newMember">
<t-dialog :header="modalTitle" :visible="userModalVisible" :width="500" :closeOnOverlayClick="false" @close="userModalVisible = false">
<t-form ref="form" :data="form" :labelWidth="80" :rules="formValidate">
<t-form-item label="手机号" name="mobile">
<t-input placeholder="请输入要添加的会员手机号码" maxlength="11" style="width: 75%" v-model="form.mobile" autocomplete="off" @change="checkClerks" />
<t-button v-if="!memberCheck" style="margin-left:8px" @click="checkClerk">校验</t-button>
<t-button v-if="memberCheck" style="margin-left:8px" @click="checkAgainClerk">重新校验</t-button>
</t-form-item>
<t-form-item v-if="newMember" label="用户名" name="username">
<t-input v-model="form.username" autocomplete="off" />
</t-form-item>
<t-form-item v-if="oldMember" label="用户名" name="username">
<t-input v-model="form.username" autocomplete="off" disabled />
</t-form-item>
<t-form-item label="密码" name="password" v-if="newMember" :status="errorPass ? 'error' : undefined" :tips="errorPass">
<t-input type="password" v-model="form.password" autocomplete="off" />
</t-form-item>
<t-form-item label="超级管理员" name="isSuper" v-if="newMember || oldMember">
<t-radio-group v-model="form.isSuper">
<t-radio :value="1">是</t-radio>
<t-radio :value="0">否</t-radio>
</t-radio-group>
</t-form-item>
<t-form-item label="角色" name="roles" v-if="(oldMember || newMember) && form.isSuper == 0">
<t-select v-model="form.roles" multiple>
<t-option v-for="item in roleList" :key="item.id" :value="item.id" :label="item.name" />
</t-select>
</t-form-item>
<t-form-item label="所属部门" v-if="oldMember || newMember">
<department-tree-choose @on-change="handleSelectDepTree" ref="depTree"></department-tree-choose>
</Form-item>
</Form>
<div slot="footer">
<Button type="text" @click="userModalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="submitUser">提交</Button>
</div>
</Modal>
</t-form-item>
</t-form>
<template #footer>
<t-button variant="text" @click="userModalVisible = false">取消</t-button>
<t-button theme="primary" :loading="submitLoading" @click="submitUser">提交</t-button>
</template>
</t-dialog>
</div>
</template>
@@ -186,11 +126,12 @@ export default {
loading: true, // 加载状态
selectCount: 0, // 已选数量
selectList: [], // 已选数据列表
selectedRowKeys: [],
searchForm: { // 请求参数
clerkName: "",
departmentId: "",
pageNumber: 1,
pageSize: 10,
pageSize: 20,
sort: "createTime",
order: "desc"
},
@@ -257,7 +198,7 @@ export default {
},
{
title: "店主",
key: "status",
key: "shopkeeper",
align: "center",
width: 130,
render: (h, params) => {
@@ -284,7 +225,7 @@ export default {
},
{
title: "超级管理员",
key: "status",
key: "isSuper",
align: "center",
width: 130,
render: (h, params) => {
@@ -444,6 +385,20 @@ export default {
total: 0, // 总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
methods: {
// 初始化数据
init() {
@@ -534,18 +489,25 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getUserList();
},
// 排序
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order == "normal") {
this.searchForm.order = "";
changeSort(sort) {
this.searchForm.sort = sort && (sort.sortBy || sort.key) || this.searchForm.sort;
if (sort && (typeof sort.descending !== 'undefined')) {
this.searchForm.order = sort.descending ? 'desc' : 'asc';
} else if (sort && sort.order) {
this.searchForm.order = sort.order === 'normal' ? '' : sort.order;
}
this.getUserList();
},
onSelectChange(selectedRowKeys, { selectedRowData } = {}) {
this.selectedRowKeys = selectedRowKeys || [];
const rows = selectedRowData || [];
this.selectList = rows;
this.selectCount = rows.length;
},
// 获取角色列表
getRoleList() {
let params = {
@@ -743,7 +705,9 @@ export default {
},
// 清除选中状态
clearSelectAll() {
this.$refs.table.selectAll(false);
this.selectedRowKeys = [];
this.selectList = [];
this.selectCount = 0;
},
// 批量删除
delAll() {

View File

@@ -8,7 +8,7 @@
<br>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page :current="pageNumber" :total="total" :page-size="pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small" show-total
<Page :current="pageNumber" :total="total" :page-size="pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small" show-total
show-elevator show-sizer></Page>
</Row>
</Card>
@@ -221,7 +221,7 @@ export default {
],
data: [], // 角色数据
pageNumber: 1, // 页数
pageSize: 10, // 每页数量
pageSize: 20, // 每页数量
total: 0, // 总数
permData: [], // 菜单权限数据
editRolePermId: "", // 编辑权限id
@@ -241,18 +241,21 @@ export default {
this.getPermList();
},
// 渲染部门前icon
renderContent(h, { root, node, data }) {
let icon = "";
if (data.level == 0) {
icon = "ios-navigate";
} else if (data.level == 1) {
icon = "md-list-box";
} else if (data.level == 2) {
icon = "md-list";
} else if (data.level == 3) {
icon = "md-radio-button-on";
renderContent(h, ctx) {
const node = (ctx && ctx.node) || null
const data = (ctx && ctx.data) || (node && node.data) || {}
const level = data.level == null ? 0 : data.level
let icon = ""
if (level == 0) {
icon = "ios-navigate"
} else if (level == 1) {
icon = "md-list-box"
} else if (level == 2) {
icon = "md-list"
} else if (level == 3) {
icon = "md-radio-button-on"
} else {
icon = "md-radio-button-off";
icon = "md-radio-button-off"
}
return h(
"span",
@@ -302,7 +305,7 @@ export default {
),
]),
]
);
)
},
// 分页 修改页码
changePage(v) {
@@ -743,14 +746,14 @@ export default {
margin-right: 20px;
}
.permModal {
.ivu-modal-body {
.t-dialog__body {
max-height: 560px;
overflow: auto;
}
}
.depModal {
.ivu-modal-body {
.t-dialog__body {
max-height: 500px;
overflow: auto;
}

View File

@@ -1,5 +1,5 @@
::v-deep .ivu-modal-mask,::v-deep .ivu-modal-wrap{
::v-deep .t-dialog{
z-index: 800;
}
.decorate-view-link{

View File

@@ -143,7 +143,7 @@
<Card class="card">
<div>
<h4>订退单统计</h4>
<div class="breadcrumb" style="margin-bottom:20px;">
<div class="breadcrumb mb_20">
<RadioGroup v-model="orderOrRefund" type="button" size="small" button-style="solid">
<Radio :label="1">订单</Radio>
<Radio :label="0">退单</Radio>
@@ -152,7 +152,18 @@
<div>
<Table stripe :columns="columns" :data="data"></Table>
</div>
<Page @on-change="pageNumberChange" @on-page-size-change="pageSizeChange" class="mt_10" show-total show-elevator :total="total" />
<Page
@on-change="pageNumberChange"
@on-page-size-change="pageSizeChange"
class="mt_10"
show-total
show-elevator
show-sizer
:total="total"
:current="refundParams.pageNumber"
:page-size="refundParams.pageSize"
:page-size-opts="[20, 50, 100]"
/>
</div>
</Card>

View File

@@ -1,9 +1,9 @@
<template>
<div>
<Card class="card fixed-bottom">
<t-card class="card fixed-bottom">
<affixTime @selected="clickBreadcrumb" />
</Card>
<Card class="card">
</t-card>
<t-card class="card">
<div>
<h4>流量概况</h4>
@@ -29,21 +29,21 @@
</div>
</Card>
</t-card>
<Card class="card">
<t-card class="card">
<div>
<h4>流量趋势</h4>
<div id="orderChart"></div>
</div>
</Card>
</t-card>
<Card class="card">
<t-card class="card">
<div>
<h4>客户增长报表</h4>
<Table class="table" stripe :columns="columns" :data="data"></Table>
<t-table class="table" :columns="tColumns" :data="data" rowKey="date"></t-table>
</div>
</Card>
</t-card>
</div>
</template>
<script>
@@ -110,6 +110,15 @@ export default {
data: [], // 客户增长报表数据
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
return nc
})
}
},
watch: {
params: {
handler(val) {

View File

@@ -35,7 +35,7 @@
cursor: pointer;
.ivu-card-body {
.t-card__body {
padding: 0;
}
@@ -228,7 +228,7 @@
}
/* Checkbox默认的样式 */
.check-box {
.ivu-checkbox {
.t-checkbox {
position: absolute;
right: 10px;
top: 10px;
@@ -236,27 +236,27 @@
}
}
/* 覆盖iView默认的Checkbox样式 */
.ivu-checkbox-wrapper {
.t-checkbox {
/*font-size: 16px; !* 修改字体大小 *!*/
/*color: #495060; !* 修改文本颜色 *!*/
/* 添加其他需要的样式 */
}
.ivu-checkbox-inner {
.t-checkbox__input {
/*width: 20px; !* 修改选框大小 *!*/
/*height: 20px;*/
/*border-color: #dcdee2; !* 修改边框颜色 *!*/
/* 添加其他需要的样式 */
}
/* 当Checkbox被选中时的样式 */
.ivu-checkbox-checked .ivu-checkbox-inner {
.t-is-checked .t-checkbox__input {
/*background-color: #2db7f5; !* 修改选中时的背景颜色 *!*/
}
/* 当Checkbox不可用时的样式 */
.ivu-checkbox-disabled .ivu-checkbox-inner {
.t-is-disabled .t-checkbox__input {
/*background-color: #e9e9e9; !* 修改禁用状态下的背景颜色 *!*/
}
.demo-tree-render .ivu-tree-title{
.demo-tree-render .t-tree__label{
width: 94%;
}
}

View File

@@ -18,7 +18,7 @@
.table {
flex: 11;
}
.ivu-card {
.t-card {
width: 100%;
}
.modal-footer {
@@ -78,7 +78,7 @@
<Col :span="isComponent?5:4">
<div class="file-list">
<div class="article-category mr_10">
<Tree :data="treeData" :render="renderContent" @on-select-change.self="handleCateChange" class="demo-tree-render"></Tree>
<Tree :data="treeData" :render="renderContent" @on-select-change="handleCateChange" class="demo-tree-render"></Tree>
<div class="group-row flex" v-if="!isComponent">
<Button @click="handleClickAddGroup">添加分组</Button>
</div>
@@ -149,7 +149,7 @@
</CheckboxGroup>
</div>
<div class="page-box">
<Page :total="total" :page-size="searchForm.pageSize" show-elevator @on-change="pageChange" size="small" />
<Page :total="total" :page-size="searchForm.pageSize" show-elevator show-sizer :page-size-opts="[20, 50, 100]" @on-change="pageChange" size="small" />
</div>
</div>
</Col>
@@ -761,35 +761,30 @@ export default {
this.searchForm.pageNumber = value;
this.getDataList();
},
// 自定义tree节点显示内容交互
renderContent (h, { root, node, data }) {
if (data.value === '0') {
return h('span', {style: {display: 'inline-block', width: '100%'}},
[
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}}, [])
]
);
} else {
return h('span', {style: {display: 'inline-block', width: '100%'}},
[
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}},
[
h("Dropdown", {style: {marginLeft: "4px"}},
[
h("Icon", {props: {type: 'ios-more', size: "20",}, style: {display: 'inline-block'}, on:{click: () => {}}}),
h("DropdownMenu", {slot: "list"
}, [
h("DropdownItem", { nativeOn:{click: () => {this.handleContextMenuEdit(root, node, data)}} }, "编辑"),
h("DropdownItem", { nativeOn:{click: () => {this.handleContextMenuDelete(data)}} }, "删除"),
// 自定义tree节点显示内容交互(兼容 t-tree 的 ctx 形态)
renderContent(h, ctx) {
const node = (ctx && ctx.node) || null
const data = (ctx && ctx.data) || (node && node.data) || {}
const isRoot = data && (data.value === '0' || data.id === '0')
const titleVNode = h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)])
if (isRoot) {
return h('span', { style: { display: 'inline-block', width: '100%' } }, [
titleVNode,
h('span', { style: { display: 'inline-block', float: 'right', marginRight: '10px' } }, [])
])
]),
])
]
);
}
return h('span', { style: { display: 'inline-block', width: '100%' } }, [
titleVNode,
h('span', { style: { display: 'inline-block', float: 'right', marginRight: '10px' } }, [
h('Dropdown', { style: { marginLeft: '4px' } }, [
h('Icon', { props: { type: 'ios-more', size: '20' }, style: { display: 'inline-block' } }),
h('DropdownMenu', { slot: 'list' }, [
h('DropdownItem', { nativeOn: { click: () => { this.handleContextMenuEdit(null, node, data) } } }, '编辑'),
h('DropdownItem', { nativeOn: { click: () => { this.handleContextMenuDelete(data) } } }, '删除')
])
])
])
])
},

View File

@@ -19,7 +19,6 @@ let externals = {
axios: "axios",
"vue-router": "VueRouter",
vuex: "Vuex",
"view-design": "iview",
"vue-lazyload": "VueLazyload",
"js-cookie": "Cookies",
"sockjs-client": "SockJS",
@@ -28,14 +27,13 @@ let externals = {
// 使用CDN的内容
let cdn = {
css: ["https://cdn.pickmall.cn/cdn/iview.css"],
css: [],
js: [
// vue must at first!
"https://cdn.pickmall.cn/cdn/vue.min.js",
"https://cdn.pickmall.cn/cdn/vuex.min.js",
"https://cdn.pickmall.cn/cdn/vue-router.min.js",
"https://cdn.pickmall.cn/cdn/axios.min.js",
"https://cdn.pickmall.cn/cdn/iview.min.js",
"https://cdn.pickmall.cn/cdn/vue-lazyload.min.js",
"https://cdn.pickmall.cn/cdn/js.cookie.min.js",
"https://cdn.pickmall.cn/cdn/sockjs.min.js",