diff --git a/manager/src/main.js b/manager/src/main.js index 67b7aa6f..ac27719d 100644 --- a/manager/src/main.js +++ b/manager/src/main.js @@ -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 = { diff --git a/seller/package.json b/seller/package.json index ff1352eb..6b1b489b 100644 --- a/seller/package.json +++ b/seller/package.json @@ -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" }, diff --git a/seller/public/config.js b/seller/public/config.js index e435fb90..87161bcb 100644 --- a/seller/public/config.js +++ b/seller/public/config.js @@ -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: { diff --git a/seller/src/App.vue b/seller/src/App.vue index c339a6b7..1f699a41 100644 --- a/seller/src/App.vue +++ b/seller/src/App.vue @@ -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{ diff --git a/seller/src/api/member.js b/seller/src/api/member.js index 1bcd08f3..8ee35b0c 100644 --- a/seller/src/api/member.js +++ b/seller/src/api/member.js @@ -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); diff --git a/seller/src/libs/axios.js b/seller/src/libs/axios.js index a61bcf61..5680ed81 100644 --- a/seller/src/libs/axios.js +++ b/seller/src/libs/axios.js @@ -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 = diff --git a/seller/src/libs/util.js b/seller/src/libs/util.js index 62c905d7..216eb426 100644 --- a/seller/src/libs/util.js +++ b/seller/src/libs/util.js @@ -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() + } + }) } }) diff --git a/seller/src/main.js b/seller/src/main.js index 1b54d1f7..2e85fa32 100644 --- a/seller/src/main.js +++ b/seller/src/main.js @@ -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 }) + } +}) diff --git a/seller/src/router/index.js b/seller/src/router/index.js index 7ab1a445..1adc189e 100644 --- a/seller/src/router/index.js +++ b/seller/src/router/index.js @@ -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); }); diff --git a/seller/src/router/router.js b/seller/src/router/router.js index e47bb194..003e2012 100644 --- a/seller/src/router/router.js +++ b/seller/src/router/router.js @@ -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: "创建直播", diff --git a/seller/src/styles/table-common.scss b/seller/src/styles/table-common.scss index efaf5984..b5d28c73 100644 --- a/seller/src/styles/table-common.scss +++ b/seller/src/styles/table-common.scss @@ -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; -} \ No newline at end of file +} diff --git a/seller/src/styles/theme.less b/seller/src/styles/theme.less deleted file mode 100644 index 472f74b8..00000000 --- a/seller/src/styles/theme.less +++ /dev/null @@ -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; diff --git a/seller/src/views/ForgetPassword.vue b/seller/src/views/ForgetPassword.vue index 915563be..18574b02 100644 --- a/seller/src/views/ForgetPassword.vue +++ b/seller/src/views/ForgetPassword.vue @@ -292,7 +292,7 @@ export default { .other-login { margin: 0 auto; - .ivu-icon { + .t-icon { font-size: 24px; } } diff --git a/seller/src/views/distribution/distributionGoods.vue b/seller/src/views/distribution/distributionGoods.vue index f4990787..dd7906d7 100644 --- a/seller/src/views/distribution/distributionGoods.vue +++ b/seller/src/views/distribution/distributionGoods.vue @@ -1,22 +1,21 @@