Commit 72a67316 authored by shangtx's avatar shangtx

Merge branch 'dev' into 'master'

Dev

See merge request !5
parents 68e9d6cd 92f1c5ab
This diff is collapsed.
......@@ -15,6 +15,8 @@
"@antv/g2": "4.2.4",
"@babel/polyfill": "7.0.0",
"@babel/runtime": "7.2.0",
"@wangeditor/editor": "^5.1.14",
"@wangeditor/editor-for-vue": "^1.0.2",
"ant-design-vue": "1.7.8",
"axios": "0.18.0",
"dayjs": "1.7.7",
......@@ -25,11 +27,10 @@
"lodash.pick": "4.4.0",
"nprogress": "0.2.0",
"simple-lightbox": "^2.1.0",
"vue": "2.6.11",
"vue": "2.6.14",
"vue-ls": "3.2.0",
"vue-router": "3.0.1",
"vuex": "3.0.1",
"wangeditor": "^4.7.5"
"vuex": "3.0.1"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "7.2.0",
......@@ -42,7 +43,7 @@
"eslint-plugin-vue": "6.2.2",
"less": "3.8.1",
"less-loader": "4.1.0",
"vue-template-compiler": "2.6.11"
"vue-template-compiler": "2.6.14"
},
"postcss": {
"plugins": {
......
<!--
基于wangEditor的vue的富文本编辑器,请通过组件的ref直接设置和获取富文本内容
由于wangEditor本身的特性(也许是bug),通过双向绑定和回调函数的方式直接修改外部的内容变量会引发末尾回车键失效的问题
文档地址 https://www.wangeditor.com/doc/
-->
<template>
<a-spin :spinning="loading">
<div class="wangeditor-atkj-wrapper" :id="id"></div>
<div class="wangeditor-atkj-wrapper">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
:style="`height: ${height}px; overflow-y: auto`"
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="onCreated"
/>
</div>
</a-spin>
</template>
<script>
// 引入 wangEditor
import wangEditor from 'wangeditor'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
export default {
name: 'RichTextEditor',
components: { Editor, Toolbar },
props: {
id: {
type: String,
default: () => 'wangeditor-atkj-wrapper-default-id'
},
height: {
type: Number,
default: () => 300
......@@ -37,181 +43,86 @@ export default {
data() {
return {
editor: null,
loading: false
loading: false,
html: '<p><br></p>',
editorConfig: {
MENU_CONF: {
uploadImage: {
server: `${process.env.VUE_APP_URL}upload?fileType=IMG`,
timeout: 5000,
fieldName: 'files',
headers: { Authorization: this.getToken() },
customInsert: function (result, insertImgFn) {
insertImgFn(result.data.urls[0])
}
},
uploadVideo: {
server: `${process.env.VUE_APP_URL}upload?fileType=VIDEO`,
timeout: 5000,
fieldName: 'files',
headers: { Authorization: this.getToken() },
onBeforeUpload() {
this.loading = true
},
onFailed() {
this.loading = false
},
onError() {
this.loading = false
},
customInsert(res, insertFn) {
if (res.code == 200) {
insertFn(res.data.urls[0])
} else {
this.$message.error('上传失败')
this.loading = false
}
}
}
}
},
toolbarConfig: {},
mode: 'default'
}
},
beforeDestroy() {
this.editor.destroy()
this.editor = null
},
mounted() {
if (this.editor != null) {
return
}
this.init()
},
activated() {
if (this.editor != null) {
return
}
this.init()
const editor = this.editor
if (editor == null) return
editor.destroy()
},
methods: {
onCreated(editor) {
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
},
// 设置内容
setContent(v) {
this.editor.txt.html(v)
console.info('got data', v)
this.$nextTick(() => {
this.html = v
})
},
// 获取内容
getContent() {
return this.editor.txt.html()
return this.html
},
// 清空内容
clear() {
this.editor.txt.clear()
this.html = '<p></p>'
},
init() {
const _this = this
const editor = new wangEditor(`.wangeditor-atkj-wrapper#${this.id}`)
// 配置 onchange 回调函数,将数据同步到 vue 中
editor.config.showLinkImg = false //关闭网络路径图片方式
editor.config.uploadImgServer = `${process.env.VUE_APP_URL}upload?fileType=IMG`
editor.config.uploadFileName = 'files' // formdata中的name属性
var token = ''
if (this.isSessionStorage) {
token = sessionStorage.getItem('Access-Token')
} else {
token = localStorage.getItem('Access-Token')
}
editor.config.uploadImgHeaders = {
// 设置请求头
Authorization: token // 设置请求头
}
// 设置高度
editor.config.height = this.height
editor.config.uploadVideoServer = `${process.env.VUE_APP_URL}upload?fileType=VIDEO`
editor.config.uploadVideoName = 'files'
editor.config.uploadVideoHeaders = {
Authorization: localStorage.getItem('token') // 设置请求头
}
editor.config.uploadVideoMaxSize = 1024 * this.videoSizeLimit
editor.config.zIndex = 0
editor.config.uploadImgHooks = {
// 图片上传并返回结果,但图片插入错误时触发
fail: function (xhr, editor, result) {
console.error('richTextError', result)
},
// eslint-disable-next-line no-unused-vars
success: function (xhr, editor, result) {
// 图片上传并返回结果,图片插入成功之后触发
},
/**
* insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
* result 即服务端返回的接口
*/
customInsert: function (insertImgFn, result) {
insertImgFn(result.data.urls[0])
}
}
editor.config.uploadVideoHooks = {
// 视频上传并返回了结果,想要自己把视频插入到编辑器中
// 例如服务器端返回的不是 { errno: 0, data: { url : '.....'} } 这种格式,可使用 customInsert
customInsert: function (insertVideoFn, result) {
// result 即服务端返回的接口
// insertVideoFn 可把视频插入到编辑器,传入视频 src ,执行函数即可
if (result.code == 200) {
insertVideoFn(result.data.urls[0])
} else {
_this.$message.error('上传失败')
_this.loading = false
}
},
before() {
_this.loading = true
},
fail() {
_this.loading = false
},
// 上传视频出错,一般为 http 请求的错误
error() {
_this.loading = false
},
// 上传视频超时
timeout() {
_this.loading = false
}
}
// 自定义插入视频, 主要用来处理loading状态
editor.config.customInsertVideo = function (url) {
const videoElement = document.createElement('video')
videoElement.setAttribute('controls', 'controls')
videoElement.setAttribute('style', 'max-width:100%')
videoElement.setAttribute('src', url)
// 4、loadeddata:视频下载监听。当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时触发
// eslint-disable-next-line no-unused-vars
videoElement.addEventListener('loadeddata', function (e) {
_this.loading = false
})
/**
* 此处参考
* https://github.com/wangeditor-team/wangEditor/blob/master/src/editor/command.ts insertElem
*/
const range = editor.selection.getRange()
if (range == null) return
if (range.insertNode) {
range.insertNode(videoElement)
}
}
// 内容change
// eslint-disable-next-line no-unused-vars
editor.config.onchange = (_newHtml) => {}
// 创建编辑器
editor.create()
this.editor = editor
getToken() {
return sessionStorage.getItem('Access-Token')
}
},
// beforeDestroy() {
// 调用销毁 API 对当前编辑器实例进行销毁
// }
}
}
</script>
<style lang="less">
.wangeditor-atkj-wrapper {
.home {
width: 1200px;
margin: auto;
position: relative;
}
.home .btn {
position: absolute;
right: 0;
top: 0;
padding: 5px 10px;
cursor: pointer;
}
.home h3 {
margin: 30px 0 15px;
}
.w-e-text-container {
border: 1px solid #c9d8db;
border-top: none;
z-index: 25;
}
.w-e-toolbar {
z-index: 28 !important;
border: 1px solid rgb(243, 243, 243);
z-index: 100; /* 按需定义 */
.wangeditor-toolbar-container {
border-bottom: 1px solid #ccc;
}
}
</style>
......@@ -4,57 +4,69 @@
v-model="visible"
@ok="handleOk"
:maskClosable="false"
class="cust-modal">
class="cust-modal"
>
<a-form :form="form" ref="form">
<a-row>
<a-col :span="24">
<a-form-item v-bind="formItemLayout" label='现密码'>
<a-form-item v-bind="formItemLayout" label="现密码">
<a-input
v-decorator="[
'password',
{
rules: [{
required: true, message: '请输入密码!',
}, {
validator: this.validateToNextPassword,
}],
}
]"
type='password'
'oldPwd',
{
rules: [
{
required: true,
message: '请输入密码!'
},
{
validator: this.validateToNextPassword
}
]
}
]"
type="password"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item v-bind="formItemLayout" label='新密码'>
<a-form-item v-bind="formItemLayout" label="新密码">
<a-input
v-decorator="[
'newPassword',
{
rules: [{
required: true, message: '请输入新密码!',
}, {
validator: this.validateToNextPassword,
}],
}
]"
type='password'
'newPwd',
{
rules: [
{
required: true,
message: '请输入新密码!'
},
{
validator: this.validateToNextPassword
}
]
}
]"
type="password"
/>
</a-form-item>
<a-form-item v-bind="formItemLayout" label='确认密码' >
<a-form-item v-bind="formItemLayout" label="确认密码">
<a-input
v-decorator="[
'confirmNewPassword',
{
rules: [{
required: true, message: '请确认密码!',
}, {
validator: compareToFirstPassword,
}],
rules: [
{
required: true,
message: '请确认密码!'
},
{
validator: compareToFirstPassword
}
]
}
]"
type='password'
type="password"
@blur="handleConfirmBlur"
/>
</a-form-item>
......@@ -62,62 +74,61 @@
</a-modal>
</template>
<script>
import { editPwd } from '@/api/system/sysUserApi'
import { editPwd } from "@/api/system/sysUserApi";
export default {
beforeCreate () {
this.form = this.$form.createForm(this)
},
data() {
return {
visible: false,
confirmDirty: false,
formItemLayout: {
labelCol: {
sm: { span: 7 },
},
wrapperCol: {
sm: { span: 14 },
},
export default {
beforeCreate() {
this.form = this.$form.createForm(this)
},
data() {
return {
visible: false,
confirmDirty: false,
formItemLayout: {
labelCol: {
sm: { span: 7 }
},
wrapperCol: {
sm: { span: 14 }
}
}
}
},
methods: {
show() {
this.visible = true
},
methods: {
show() {
this.visible = true;
},
handleOk() {
this.form.validateFieldsAndScroll((err, values) => {
if (!err) {
editPwd(values).then(resp => {
if (resp && resp.code == SYS_CONST.REQUEST.SUCCEED) {
this.$emit('relogin', this.optType, values);
this.visible = false;
}
})
}
})
},
validateToNextPassword (rule, value, callback) {
const form = this.form
if (value && this.confirmDirty) {
form.validateFields(['confirmNewPassword'], { force: true })
handleOk() {
this.form.validateFieldsAndScroll((err, values) => {
if (!err) {
editPwd(values).then((resp) => {
if (resp && resp.code == SYS_CONST.REQUEST.SUCCEED) {
this.$emit('relogin', this.optType, values)
this.visible = false
}
})
}
})
},
validateToNextPassword(rule, value, callback) {
const form = this.form
if (value && this.confirmDirty) {
form.validateFields(['confirmNewPassword'], { force: true })
}
callback()
},
compareToFirstPassword(rule, value, callback) {
const form = this.form
if (value && value !== form.getFieldValue('newPwd')) {
callback('确认两次密码是否一致!')
} else {
callback()
},
compareToFirstPassword (rule, value, callback) {
const form = this.form
if (value && value !== form.getFieldValue('newPassword')) {
callback('确认两次密码是否一致!')
} else {
callback()
}
},
handleConfirmBlur (e) {
const value = e.target.value
this.confirmDirty = this.confirmDirty || !!value
},
}
},
handleConfirmBlur(e) {
const value = e.target.value
this.confirmDirty = this.confirmDirty || !!value
}
}
}
</script>
\ No newline at end of file
......@@ -3,7 +3,7 @@ const getters = {
theme: state => state.app.theme,
color: state => state.app.color,
token: state => state.user.token,
avatar: state => state.user.avatar ? state.user.avatar : 'https://antaiproduct.oss-cn-qingdao.aliyuncs.com/logo/antai-logo-small.png',
avatar: state => state.user.avatar ? state.user.avatar : 'http://chengshijiangren.oss-cn-beijing.aliyuncs.com/onsite-service-admin/img/1/1076549795625046016.png',
nickname: state => state.user.name ? state.user.name : '未命名',
welcome: state => state.user.welcome,
roles: state => state.user.roles,
......
......@@ -46,12 +46,12 @@ export default class SocketService {
static onmessage(e) {
console.info('from server', e)
const { data } = e
if (data == 1) {
if (data == '1' || data == '2') {
const message = data == '1' ? '用户已支付,请派单' : '用户已支付'
notification.open({
message: '消息提醒',
description: '用户已支付,请派单',
description: message,
key: 'orderNotification',
btn: h => {
return h(
......
......@@ -36,13 +36,18 @@
: '-'
}}
</a-descriptions-item>
<a-descriptions-item label="数量" span="2">
<a-descriptions-item label="数量">
{{ order.num || '-' }}
</a-descriptions-item>
<a-descriptions-item label="地址" span="2">
<a-descriptions-item label="当前定价(元)">
{{ order.price || '-' }}
</a-descriptions-item>
<a-descriptions-item label="地址">
{{ order.address || '-' }}
</a-descriptions-item>
<a-descriptions-item label="已支付金额(元)">
{{ order.totalPrice || '-' }}
</a-descriptions-item>
<a-descriptions-item label="需求说明" :span="2">
{{ order.demandDesc || '-' }}
</a-descriptions-item>
......@@ -84,7 +89,9 @@
hasPerm('SYS02201.SEND') &&
!past &&
(order.orderStatus == STATUS.RESERVE ||
order.orderStatus == STATUS.VALUATION)
order.orderStatus == STATUS.VALUATION ||
order.orderStatus == STATUS.PAY ||
order.orderStatus == STATUS.DISPATCH)
"
>
发送订单
......
......@@ -55,6 +55,13 @@ const columns = [
width: 130,
filter: { type: SearchType.STRING }
},
{
title: '已支付金额(元)',
dataIndex: 'totalPrice',
align: 'center',
customRender: (value) => value || '-',
width: 100,
},
{
title: '服务时间',
dataIndex: 'expectArrivalTime',
......
......@@ -10,12 +10,12 @@
<a-form-item :label="`服务大类: ${categoryName}`"> </a-form-item>
<a-col :span="11">
<a-form-item label="名称">
<a-input v-decorator="['serviceName']" />
<a-input v-decorator="['serviceName', {rules: [{required: true, message: '请填写名称'}]}]" />
</a-form-item>
</a-col>
<a-col :span="11" :offset="1">
<a-form-item label="次级标题">
<a-input v-decorator="['description']" />
<a-input v-decorator="['description', {rules: [{required: true, message: '请填写标题'}]}]" />
</a-form-item>
</a-col>
<a-col :span="5">
......
......@@ -19,17 +19,17 @@
/>
</a-col>
<a-col v-if="param.type == 3" :span="24">
<a-form-item :label="param.name" v-bind="formItemLayout">
<a-form-item :label="param.name" >
<RichText ref="RichText" :height="600" />
</a-form-item>
</a-col>
<a-col v-if="param.type == 1" :span="24">
<a-form-item :label="param.name" v-bind="formItemLayout">
<a-form-item :label="param.name" >
<a-input-number style="width: 180px" v-model="value" />
</a-form-item>
</a-col>
<a-col v-if="param.type == 2" :span="24">
<a-form-item :label="param.name" v-bind="formItemLayout">
<a-form-item :label="param.name" >
<a-input v-model="value" />
</a-form-item>
</a-col>
......@@ -65,6 +65,7 @@ export default {
this.visible = true
this.$nextTick(() => {
if (row.type == 3) {
console.info('row value', row.value)
this.$refs.RichText.setContent(row.value)
}
if (row.type == 4) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment