四种单据使用详情页改写

命名修改
修复一些小问题
master
toesbieya 6 years ago
parent ff8fab0853
commit ac7257be8b
  1. 2
      vue/src/api/document/purchase/inbound.js
  2. 125
      vue/src/assets/styles/detail-page.scss
  3. 19
      vue/src/assets/styles/element-ui.scss
  4. 10
      vue/src/assets/styles/index.scss
  5. 11
      vue/src/assets/styles/variables.scss
  6. 46
      vue/src/bizComponents/DocumentHistory/index.vue
  7. 27
      vue/src/bizComponents/DocumentSteps/index.vue
  8. 16
      vue/src/bizComponents/document/DocDetailFooter.vue
  9. 47
      vue/src/bizComponents/document/DocDetailHeader.vue
  10. 64
      vue/src/bizComponents/document/DocHistory.vue
  11. 25
      vue/src/bizComponents/document/DocSteps.vue
  12. 2
      vue/src/components/AbstractForm/AbstractFormItem.vue
  13. 23
      vue/src/components/AbstractForm/index.vue
  14. 17
      vue/src/components/AbstractTable/index.vue
  15. 2
      vue/src/components/FormDialog/index.vue
  16. 4
      vue/src/components/RegionSelector/Tree/TreeDialog.vue
  17. 6
      vue/src/components/SearchForm/index.vue
  18. 2
      vue/src/layout/components/Main.vue
  19. 1
      vue/src/layout/components/Navbar/components/HeaderSearch.vue
  20. 7
      vue/src/layout/components/Sidebar/index.vue
  21. 19
      vue/src/layout/components/TagsView/index.vue
  22. 164
      vue/src/mixins/bizDocDetailMixin.js
  23. 55
      vue/src/mixins/bizDocumentTableMixin.js
  24. 31
      vue/src/mixins/tablePageMixin.js
  25. 28
      vue/src/router/authority/modules/purchase.js
  26. 28
      vue/src/router/authority/modules/sell.js
  27. 28
      vue/src/store/modules/needSearch.js
  28. 3
      vue/src/utils/index.js
  29. 9
      vue/src/utils/route.js
  30. 8
      vue/src/views/example/stylePage.vue
  31. 103
      vue/src/views/message/manage/EditDialog.vue
  32. 168
      vue/src/views/purchase/inbound/components/EditDialog.vue
  33. 185
      vue/src/views/purchase/inbound/detail.vue
  34. 15
      vue/src/views/purchase/inbound/index.vue
  35. 211
      vue/src/views/purchase/order/components/EditDialog.vue
  36. 241
      vue/src/views/purchase/order/detail.vue
  37. 17
      vue/src/views/purchase/order/index.vue
  38. 22
      vue/src/views/sell/order/components/CustomerSelector.vue
  39. 216
      vue/src/views/sell/order/components/EditDialog.vue
  40. 217
      vue/src/views/sell/order/detail.vue
  41. 15
      vue/src/views/sell/order/index.vue
  42. 209
      vue/src/views/sell/outbound/detail.vue
  43. 15
      vue/src/views/sell/outbound/index.vue
  44. 8
      vue/src/views/stock/current/DetailDialog.vue
  45. 8
      vue/src/views/system/customer/EditDialog.vue
  46. 8
      vue/src/views/system/department/components/EditDialog.vue
  47. 8
      vue/src/views/system/resource/EditDialog.vue
  48. 8
      vue/src/views/system/role/components/EditDialog.vue
  49. 8
      vue/src/views/system/supplier/EditDialog.vue
  50. 8
      vue/src/views/system/user/components/EditDialog.vue
  51. 8
      vue/src/views/userCenter/components/Account.vue
  52. 8
      vue/src/views/userCenter/components/Avatar.vue

@ -1,6 +1,6 @@
import request from "@/config/request"
const baseUrl = '/document/purchase/inbound'
export const baseUrl = '/document/purchase/inbound'
export function getById(id) {
return request.get(`${baseUrl}/getById?id=${id}`).then(({data}) => data.data)

@ -0,0 +1,125 @@
.detail-page {
&-header {
margin: -#{$page-view-margin} -#{$page-view-margin} 0 -#{$page-view-margin};
padding: 16px 32px 0 32px;
background: #fff;
border-bottom: 1px solid #e8eaec;
> .el-row {
display: flex;
width: 100%;
margin-bottom: 12px;
@media (max-width: 768px) {
display: block;
}
}
&-close-btn {
font-size: 18px;
}
&-title {
margin-left: 5px;
font-weight: 500;
font-size: 20px;
line-height: 42px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&-left {
width: 100%;
overflow: hidden;
.el-col {
margin-bottom: 16px;
}
}
&-extra {
min-width: 242px;
margin-left: 88px;
@media (max-width: 1200px) {
margin-left: 44px;
}
@media (max-width: 992px) {
margin-left: 20px;
}
@media (max-width: 768px) {
margin-left: 0;
}
> div {
display: flex;
justify-content: space-between;
width: 200px;
}
&-title {
margin-bottom: 4px;
color: rgba(0, 0, 0, .45);
font-size: 14px;
}
&-content {
margin-top: 12px;
color: rgba(0, 0, 0, .85);
font-size: 24px;
}
}
&-description {
span {
display: inline-flex;
align-items: baseline;
}
&-label {
color: rgba(0, 0, 0, .85);
font-weight: 400;
font-size: 14px;
line-height: 1.5715;
text-align: start;
}
&-content {
color: rgba(0, 0, 0, .65);
font-size: 14px;
line-height: 1.5715;
}
}
}
> .el-form > .el-row > .el-card {
margin-top: 16px;
}
&-footer {
@include clearfix;
position: absolute;
width: 100%;
right: 0;
bottom: 0;
z-index: 99;
transition: all 0.3s ease 0s;
height: 56px;
padding: 0 24px;
line-height: 56px;
border-top: 1px solid #f0f0f0;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05);
backdrop-filter: blur(3px);
&-left {
float: left;
}
&-right {
float: right;
}
}
}

@ -24,6 +24,8 @@
.el-card__body {
height: 100%;
@include clearfix;
}
.el-card__header + .el-card__body {
@ -68,14 +70,6 @@
}
}
.el-form {
.el-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
}
.el-loading-mask {
background: #fff;
color: $--color-primary;
@ -142,6 +136,15 @@
width: 100%;
}
.el-steps {
&.el-steps--horizontal {
.el-step__line {
left: 57%;
right: -43%;
}
}
}
.el-table {
thead {
color: rgba(0, 0, 0, .85)

@ -5,6 +5,7 @@
@import "element-ui";
@import "~@ele/style/index.scss";
@import "nprogress";
@import "detail-page";
body {
height: 100%;
@ -58,14 +59,7 @@ a:hover {
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
@include clearfix;
}
.overflow-hidden {

@ -26,6 +26,17 @@ $--color-warning: $--color-deep-orange;
$--color-danger: $--color-red;
$--color-info: $--color-teal;
@mixin clearfix{
&::after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
@mixin deep-shadow {
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
}

@ -1,46 +0,0 @@
<script type="text/jsx">
export default {
name: "DocumentHistory",
functional: true,
props: {
type: String,
data: {type: Array, default: () => []}
},
render(h, context) {
const {type, data = []} = context.props
if (type === 'add') return ''
return (
<el-popover
v-on:show={context.listeners.show}
placement="bottom"
width="250"
trigger="click"
>
<el-timeline>
<el-scrollbar wrap-class="el-select-dropdown__wrap">
{
data.map(activity => (
<el-timeline-item
key={activity.id}
timestamp={activity.time}
placement="top"
>
<p>{activity.uname} {activity.type}</p>
<p>{activity.info}</p>
</el-timeline-item>
))
}
</el-scrollbar>
{data.length <= 0 ? <div className="el-timeline__empty">暂无记录</div> : ''}
</el-timeline>
<button slot="reference" class="el-dialog__headerbtn" style="right: 60px" title="历史状态记录">
<i class="el-icon-document el-dialog__close"/>
</button>
</el-popover>
)
}
}
</script>

@ -1,27 +0,0 @@
<script type="text/jsx">
export default {
name: "DocumentSteps",
functional: true,
props: {
status: Number,
type: String
},
render(h, context) {
let {status, type} = context.props
let firstStatus = type === 'add' ? 'finish' : 'success'
let secondStatus = status === 1 ? 'success' : type === 'add' ? 'wait' : 'finish'
if (status !== 2) {
return (
<el-steps align-center style="margin-top: 20px">
<el-step title="填写单据" status={firstStatus}/>
<el-step title="提交单据,等待审核" status={secondStatus}/>
<el-step title="审核通过" status="wait"/>
</el-steps>
)
}
}
}
</script>

@ -0,0 +1,16 @@
<template functional>
<div class="detail-page-footer">
<div class="detail-page-footer-left">
<slot name="left"/>
</div>
<div class="detail-page-footer-right">
<slot name="right"/>
</div>
</div>
</template>
<script>
export default {
name: "DocDetailFooter"
}
</script>

@ -0,0 +1,47 @@
<template functional>
<div class="detail-page-header">
<el-row>
<el-button
class="detail-page-header-close-btn"
type="text"
icon="el-icon-arrow-left"
@click="listeners.close"
/>
<span class="detail-page-header-title">{{props.title}}</span>
</el-row>
<el-row>
<el-row class="detail-page-header-left">
<el-col v-for="i in props.description" :key="i.label" :xs="24" :sm="12">
<span class="detail-page-header-description-label">{{i.label}}</span>
<span class="detail-page-header-description-content">{{i.content}}</span>
</el-col>
</el-row>
<div class="detail-page-header-extra">
<div>
<div v-for="i in props.extra" :key="i.title">
<div class="detail-page-header-extra-title">{{i.title}}</div>
<div class="detail-page-header-extra-content">{{i.content}}</div>
</div>
</div>
</div>
</el-row>
</div>
</template>
<script>
export default {
name: "DocDetailHeader",
props: {
title: String,
description: {
type: Array,
default: () => []
},
extra: {
type: Array,
default: () => []
}
}
}
</script>

@ -0,0 +1,64 @@
<template>
<el-card header="单据历史" style="margin-top: 16px">
<abstract-table v-loading="loading" :data="data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="操作人" prop="uname"/>
<el-table-column align="center" label="操作类型" prop="type"/>
<el-table-column align="center" label="时 间" prop="time"/>
<el-table-column align="center" label="备注" prop="info"/>
</abstract-table>
</el-card>
</template>
<script>
import AbstractTable from "@/components/AbstractTable"
import {getDocumentHistoryByPid} from "@/api/documentHistory"
import {isEmpty, timeFormat} from "@/utils"
export default {
name: "DocHistory",
components: {AbstractTable},
props: {id: String},
data() {
return {
loading: false,
data: []
}
},
watch: {
id: {
immediate: true,
handler(v) {
if (isEmpty(v)) return
getDocumentHistoryByPid(v)
.then(history => {
history.forEach(i => {
i.time = timeFormat(null, new Date(i.time))
let type = null
switch (i.type) {
case 0:
type = '撤回'
break
case 1:
type = '提交'
break
case 2:
type = '通过'
break
case 3:
type = '驳回'
break
}
i.type = type
})
this.data = history
})
}
}
}
}
</script>

@ -0,0 +1,25 @@
<script type="text/jsx">
export default {
name: "DocSteps",
functional: true,
props: {
status: Number,
finish: Number
},
render(h, context) {
const {status, finish} = context.props
const active = status === 2 && (finish === undefined || finish === 1) ? 3 : status
return (
<el-steps align-center active={active + 1}>
<el-step title="填写单据"/>
<el-step title="提交单据,等待审核"/>
<el-step title="审核通过"/>
<el-step title="单据完成"/>
</el-steps>
)
}
}
</script>

@ -1,6 +1,6 @@
<script type="text/jsx">
export default {
name: "DialogFormItem",
name: "AbstractFormItem",
functional: true,

@ -0,0 +1,23 @@
<script type="text/jsx">
export default {
name: "AbstractForm",
functional: true,
render(h, context) {
const {data, children} = context
return (
<el-form
ref="form"
label-position="right"
label-width="100px"
size="small"
status-icon
{...data}
>
<el-row>{children}</el-row>
</el-form>
)
}
}
</script>

@ -1,5 +1,5 @@
<script type="text/jsx">
import Empty from '@/components/Empty'
import Empty from "@/components/Empty"
export default {
name: "AbstractTable",
@ -7,7 +7,12 @@
functional: true,
render(h, context) {
const {data, children} = context
const {data, children, scopedSlots} = context
if (!scopedSlots.empty) {
scopedSlots.empty = () => <Empty/>
}
return (
<el-table
ref="table"
@ -17,7 +22,13 @@
{...data}
>
{children}
<Empty slot="empty"/>
{
Object
.entries(scopedSlots)
.map(([name, slot]) => (
name !== 'default' && <slot slot={name}>{slot()}</slot>
))
}
</el-table>
)
}

@ -26,7 +26,7 @@
import LoadingMask from '@/components/LoadingMask'
export default {
name: "DialogForm",
name: "FormDialog",
components: {LoadingMask},

@ -1,10 +1,10 @@
<script type="text/jsx">
import store from '@/store'
import DialogForm from "@/components/DialogForm"
import FormDialog from "@/components/FormDialog"
import {createLimitTree, getNodeId} from "@/utils/tree"
export default {
components: {DialogForm},
components: {FormDialog},
data() {
return {

@ -107,6 +107,12 @@
.searchForm {
margin-bottom: -15px;
> .el-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.searchForm__collapse {
position: relative;
bottom: 20px;

@ -22,7 +22,7 @@
width="100%"
/>
<el-backtop v-if="showBackToTop" target=".app-main .el-scrollbar__wrap" :visibility-height="400"/>
<el-backtop v-if="showBackToTop" target=".app-main .el-scrollbar__wrap" :visibility-height="400" :bottom="66"/>
</main>
</template>

@ -11,6 +11,7 @@
filterable
placeholder="搜索页面"
remote
popper-append-to-body
@change="change"
>
<el-option

@ -28,7 +28,7 @@
if (path.startsWith('/redirect')) {
return path.replace('/redirect', '')
}
return meta && meta.activeMenu ? meta.activeMenu : path
return meta.activeMenu || path
},
//pc
@ -55,11 +55,10 @@
//elMenuinitOpenedMenu()select
'$route.path'(nv, ov) {
//redirect
if (nv === '/redirect' + ov) return
if (nv === `/redirect${ov}`) return
const menu = this.$refs.menu
if (!menu) return
const item = menu.items[nv]
const item = menu.items[this.activeMenu]
if (!item) menu.openedMenus = []
else this.select(item.index, item.indexPath, item, false)
},

@ -87,6 +87,7 @@
routes.forEach(route => {
if (route.name && route.meta && route.meta.affix) {
tags.push({
//fullPath$route.fullPath
fullPath: route.fullPath,
path: route.fullPath,
name: route.name,
@ -95,7 +96,7 @@
}
if (route.children) {
const tempTags = this.filterAffixTags(route.children)
if (tempTags.length > 0) tags.push(...tempTags)
tempTags.length > 0 && tags.push(...tempTags)
}
})
return tags
@ -117,7 +118,6 @@
this.$nextTick(() => {
const tag = this.$refs.tag.find(i => i.to.path === this.$route.path)
if (!tag) return
this.$refs.scrollPane.moveToTarget(tag)
})
},
@ -128,24 +128,27 @@
* */
refreshSelectedTag(view) {
this.$store.commit('tagsView/delCachedView', view)
this.$nextTick(() => this.$router.replace({path: '/redirect' + view.fullPath}))
this.$nextTick(() => this.$router.replace({path: `/redirect${view.fullPath}`}))
},
closeSelectedTag(view) {
if (this.isAffix(view)) return
this.$store.dispatch('tagsView/delView', view)
this.$store
.dispatch('tagsView/delView', view)
.then(() => this.isActive(view) && this.gotoLastView())
},
closeOthersTags() {
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag)
this.$store
.dispatch('tagsView/delOthersViews', this.selectedTag)
.then(() => {
if (this.selectedTag.path !== this.$route.path) {
this.$router.push(this.selectedTag)
return this.$router.push(this.selectedTag)
}
})
},
closeAllTags() {
this.$store.dispatch('tagsView/delAllViews')
.then(() => this.gotoLastView())
this.$store
.dispatch('tagsView/delAllViews')
.then(this.gotoLastView)
},
gotoLastView() {

@ -1,34 +1,40 @@
import AbstractForm from '@/components/AbstractForm'
import AbstractFormItem from "@/components/AbstractForm/AbstractFormItem"
import AbstractTable from "@/components/AbstractTable"
import DocDetailHeader from "@/bizComponents/document/DocDetailHeader"
import DocDetailFooter from "@/bizComponents/document/DocDetailFooter"
import DocHistory from '@/bizComponents/document/DocHistory'
import DocSteps from '@/bizComponents/document/DocSteps'
import UploadFile from '@/components/UploadFile'
import DialogForm from '@/components/DialogForm'
import DialogFormItem from "@/components/DialogForm/DialogFormItem"
import DocumentSteps from '@/bizComponents/DocumentSteps'
import DocumentHistory from '@/bizComponents/DocumentHistory'
import dialogMixin from "@/mixins/dialogMixin"
import {commonMethods} from "@/mixins/bizDocumentTableMixin"
import {isEmpty, mergeObj, resetObj, timeFormat} from '@/utils'
import {isEmpty, mergeObj} from '@/utils'
import {elAlert, elConfirm, elPrompt, elSuccess} from "@/utils/message"
import {getDocumentHistoryByPid} from "@/api/documentHistory"
import {deleteUpload} from "@/utils/file"
import {auth} from "@/utils/auth"
import {closeCurrentPage} from "@/utils/route"
export default {
mixins: [dialogMixin],
components: {DialogForm, DialogFormItem, DocumentSteps, DocumentHistory, UploadFile},
components: {
AbstractForm,
AbstractFormItem,
AbstractTable,
DocDetailHeader,
DocDetailFooter,
DocHistory,
DocSteps,
UploadFile
},
props: {
//dialog显隐
value: Boolean,
//编辑模式,see,add,edit
type: {type: String, default: 'see'},
//单据id
id: String,
baseUrl: String
//编辑模式,see,add,edit
type: String
},
data() {
return {
//dialog loading标志
loading: true,
//关闭dialog后是否需要更新列表
needSearch: false,
//单据提交历史
history: [],
form: {
@ -49,51 +55,51 @@ export default {
rules: {}
}
},
computed: {
//dialog标题
title() {
if (isEmpty(this.type)) return ''
switch (this.type) {
case 'see':
return this.documentName + '信息'
return `查看${this.docName}${this.form.id}`
case 'add':
return '添加' + this.documentName
return `添加${this.docName}`
case 'edit':
return '编辑' + this.documentName
return `编辑${this.docName}${this.form.id}`
}
},
user() {
return this.$store.state.user
},
/*
* 权限判断以及根据状态控制是否可编辑
* */
//权限判断以及根据状态控制是否可编辑
canSave() {
//add模式有添加权限、edit模式有编辑权限且status=0
return this.type === 'add' && auth(this.baseUrl + '/add')
|| this.form.status === 0 && this.type === 'edit' && auth(this.baseUrl + '/update')
return this.type === 'add' && auth(`${this.baseUrl}/add`)
|| this.form.status === 0 && this.type === 'edit' && auth(`${this.baseUrl}/update`)
},
canCommit() {
//有提交权限、add模式或edit模式且status=0
return auth(this.baseUrl + '/commit') && (this.type === 'add' || this.type === 'edit' && this.form.status === 0)
return auth(`${this.baseUrl}/commit`)
&& (this.type === 'add' || this.type === 'edit' && this.form.status === 0)
},
canWithdraw() {
//有撤回权限、当前用户是创建人、edit模式且status=1
return auth(this.baseUrl + '/withdraw')
return auth(`${this.baseUrl}/withdraw`)
&& this.type === 'edit'
&& this.user.id === this.form.cid
&& this.form.status === 1
},
canPass() {
//有通过权限、edit模式且status=1
return auth(this.baseUrl + '/pass') && this.type === 'edit' && this.form.status === 1
return auth(`${this.baseUrl}/pass`) && this.type === 'edit' && this.form.status === 1
},
canReject() {
//有驳回权限、edit模式且status=1
return auth(this.baseUrl + '/reject') && this.type === 'edit' && this.form.status === 1
return auth(`${this.baseUrl}/reject`) && this.type === 'edit' && this.form.status === 1
}
},
methods: {
...commonMethods,
@ -107,14 +113,12 @@ export default {
if (!isEmpty(valid)) return elAlert(valid)
}
this.loading = true
let promise = this.type === 'add' ? this.api.add(this.form) : this.api.update(this.form)
const promise = this.type === 'add' ? this.api.add(this.form) : this.api.update(this.form)
promise
.then(({data, msg}) => {
this.needSearch = true
this.needSearch()
elSuccess(msg)
const id = this.type === 'add' ? data : this.form.id
this.$emit('update:type', 'edit')
this.init(id)
this.afterSaveOrCommit(data)
})
.catch(() => this.loading = false)
})
@ -134,10 +138,8 @@ export default {
.then(() => this.api.commit(this.form))
.then(({data, msg}) => {
elSuccess(msg)
this.needSearch = true
const id = this.type === 'add' ? data : this.form.id
this.$emit('update:type', 'edit')
this.init(id)
this.needSearch()
this.afterSaveOrCommit(data)
})
.catch(() => this.loading = false)
})
@ -153,7 +155,7 @@ export default {
})
.then(({msg}) => {
elSuccess(msg)
this.needSearch = true
this.needSearch()
this.init(this.form.id)
})
.catch(() => this.loading = false)
@ -169,10 +171,10 @@ export default {
})
.then(({msg}) => {
elSuccess(msg)
this.needSearch = true
this.closeDialog()
this.needSearch()
return this.close()
})
.finally(() => this.loading = false)
.catch(() => this.loading = false)
},
//驳回单据,状态由待审核->拟定
@ -185,71 +187,42 @@ export default {
})
.then(({msg}) => {
elSuccess(msg)
this.needSearch = true
this.closeDialog()
})
.finally(() => this.loading = false)
},
//获取单据的提交历史
getHistory() {
if (isEmpty(this.id) || this.history.length > 0) return
getDocumentHistoryByPid(this.id)
.then(history => {
history.forEach(i => {
i.time = timeFormat(null, new Date(i.time))
let type = null
switch (i.type) {
case 0:
type = '撤回'
break
case 1:
type = '提交'
break
case 2:
type = '通过'
break
case 3:
type = '驳回'
break
}
i.type = type
})
this.history = history
this.needSearch()
return this.close()
})
.catch(() => this.loading = false)
},
//初始化单据信息
init(id) {
this.loading = true
if (isEmpty(id)) {
return elAlert(`获取${this.documentName}数据失败,请传入id`, this.closeDialog)
return elAlert(`获取${this.docName}数据失败,请传入id`, this.close)
}
this.api.getById(id)
.then(data => {
if (!data || id !== data.id) return Promise.reject()
return Promise.resolve(mergeObj(this.form, data))
})
.then(() => this.afterInit ? this.afterInit() : Promise.resolve())
.then(this.afterInit || Promise.resolve)
.catch(e => {
console.log(e)
return elAlert(`获取${this.documentName}数据失败,请重试`, () => this.cancel())
return elAlert(`获取${this.docName}数据失败,请重试`, this.close)
})
.finally(() => this.loading = false)
},
//dialog打开时
open() {
this.needSearch = false
this.loading = false
if (this.type !== 'add') return this.init(this.id)
//保存、提交成功后需要判断后续动作
afterSaveOrCommit(data) {
if (this.type === 'add') {
const editUrl = `${this.baseUrl}/detail/edit/${data}`
return closeCurrentPage(editUrl)
}
else return this.init(this.form.id)
},
//关闭dialog并清除单据数据
cancel() {
this.closeDialog()
this.needSearch && this.$emit('search')
//关闭页面
close() {
//删除未保存的上传附件
const deleteArr = []
if (this.form.uploadImageList.length > 0) {
@ -259,17 +232,11 @@ export default {
deleteUpload(deleteArr).catch(e => ({}))
}
//延时清除表单数据
setTimeout(() => this.clearForm(), 200)
this.loading = false
return closeCurrentPage(this.baseUrl)
},
//清除单据数据
clearForm() {
resetObj(this.form)
this.history = []
this.parentSubList && (this.parentSubList = [])
this.$nextTick(() => this.$refs.form.clearValidate())
needSearch() {
this.$store.commit('needSearch/emit', this.baseUrl)
},
//附件操作
@ -281,5 +248,10 @@ export default {
const index = this.form.uploadImageList.findIndex(i => i.url === file.url)
if (index > -1) this.form.uploadImageList.splice(index, 1)
}
},
mounted() {
this.loading = false
if (this.type !== 'add') return this.init(this.id)
}
}

@ -32,7 +32,9 @@ export const commonMethods = {
export default {
mixins: [tableMixin],
components: {LinerProgress},
data() {
return {
searchForm: {
@ -40,7 +42,6 @@ export default {
cname: null,
vname: null
},
editDialog: false,
temp: {
status: [],
ctime: [],
@ -48,30 +49,25 @@ export default {
}
}
},
computed: {
canAdd() {
return auth(this.baseUrl + '/add')
return auth(`${this.baseUrl}/add`)
},
canUpdate() {
return auth(this.baseUrl + '/update')
|| auth(this.baseUrl + '/withdraw')
|| auth(this.baseUrl + '/pass')
|| auth(this.baseUrl + '/reject')
return auth(`${this.baseUrl}/update`)
|| auth(`${this.baseUrl}/withdraw`)
|| auth(`${this.baseUrl}/pass`)
|| auth(`${this.baseUrl}/reject`)
},
canDel() {
return auth(this.baseUrl + '/del')
return auth(`${this.baseUrl}/del`)
},
canExport() {
return auth(this.baseUrl + '/export')
return auth(`${this.baseUrl}/export`)
},
},
watch: {
editDialog(v) {
if (!v && this.row && this.row._external) {
this.row = null
}
}
},
methods: {
...commonMethods,
search() {
@ -103,23 +99,25 @@ export default {
},
add() {
this.row = null
this.type = 'add'
this.editDialog = true
this.$router.push(`${this.$route.path}/detail/add`)
},
see() {
if (isEmpty(this.row)) return elError('请选择要查看的单据')
this.type = 'see'
this.editDialog = true
this.$router.push(`${this.$route.path}/detail/see/${this.row.id}`)
},
edit() {
if (isEmpty(this.row)) return elError('请选择要编辑的单据')
this.type = 'edit'
this.editDialog = true
this.$router.push(`${this.$route.path}/detail/edit/${this.row.id}`)
},
del() {
if (isEmpty(this.row)) return elError('请选择要删除的单据')
if (this.row.status !== 0) return elError('只有状态为【拟定】时才能删除')
if (isEmpty(this.row)) {
return elError('请选择要删除的单据')
}
if (this.row.status !== 0) {
return elError('只有状态为【拟定】时才能删除')
}
if (this.config.operating) return
elConfirm(`确定删除单据【${this.row.id}】?`)
.then(() => {
this.config.operating = true
@ -132,16 +130,7 @@ export default {
.finally(() => this.config.operating = false)
},
downloadExcel() {
exportExcel(this.baseUrl + '/export', this.mergeSearchForm(), this.excel)
exportExcel(`${this.baseUrl}/export`, this.mergeSearchForm(), this.excel)
}
},
activated() {
const {type, id} = this.$route.params
if (!['see', 'edit'].includes(type) || isEmpty(id)) return
this.row = null
this.$nextTick(() => {
this.row = {id, _external: true}
this[type]()
})
}
}

@ -24,9 +24,24 @@ const mixin = {
components: {AbstractTable},
computed: {
tablePageNeedSearchMap() {
return this.$store.state.needSearch.map
}
},
watch: {
row(v) {
!v && this.$refs.table && this.$refs.table.setCurrentRow()
},
tablePageNeedSearchMap: {
deep: true,
handler(v) {
if (this._routePath === this.$route.path){
this.reSearch(v)
}
}
}
},
@ -43,9 +58,25 @@ const mixin = {
this.searchForm.page = v
this.search()
},
reSearch(map) {
const path = this._routePath
if (map.hasOwnProperty(path) && map[path]) {
this.search()
this.$store.commit('needSearch/renew', path)
}
}
},
activated() {
this.reSearch(this.tablePageNeedSearchMap)
},
mounted() {
//注册needSearch事件
this._routePath = this.$route.path
this.$store.commit('needSearch/init', this._routePath)
this.search()
}
}

@ -3,7 +3,7 @@ import Layout from '@/layout'
import {lazyLoadView} from "@/router/util"
const router = {
path: '/purchase',
path: '/document/purchase',
component: Layout,
alwaysShow: true,
meta: {title: '采购管理', icon: 'shopping'},
@ -14,11 +14,37 @@ const router = {
component: () => lazyLoadView(import('@/views/purchase/order')),
meta: {title: '采购订单'}
},
{
path: 'order/detail/:type(see|add|edit)/:id?',
name: 'purchaseOrderDetail',
hidden: true,
props: true,
component: () => lazyLoadView(import('@/views/purchase/order/detail')),
meta: {
title: '采购订单详情',
activeMenu: '/document/purchase/order',
noCache: true,
isDetailPage: true
}
},
{
path: 'inbound',
name: 'purchaseInbound',
component: () => lazyLoadView(import('@/views/purchase/inbound')),
meta: {title: '采购入库'}
},
{
path: 'inbound/detail/:type(see|add|edit)/:id?',
name: 'purchaseInboundDetail',
hidden: true,
props: true,
component: () => lazyLoadView(import('@/views/purchase/inbound/detail')),
meta: {
title: '采购入库详情',
activeMenu: '/document/purchase/inbound',
noCache: true,
isDetailPage: true
}
}
]
}

@ -3,7 +3,7 @@ import Layout from '@/layout'
import {lazyLoadView} from "@/router/util"
const router = {
path: '/sell',
path: '/document/sell',
component: Layout,
alwaysShow: true,
meta: {title: '销售管理', icon: 'sell'},
@ -14,11 +14,37 @@ const router = {
component: () => lazyLoadView(import('@/views/sell/order')),
meta: {title: '销售订单'}
},
{
path: 'order/detail/:type(see|add|edit)/:id?',
name: 'purchaseOrderDetail',
hidden: true,
props: true,
component: () => lazyLoadView(import('@/views/sell/order/detail')),
meta: {
title: '销售订单详情',
activeMenu: '/document/sell/order',
noCache: true,
isDetailPage: true
}
},
{
path: 'outbound',
name: 'sellOutbound',
component: () => lazyLoadView(import('@/views/sell/outbound')),
meta: {title: '销售出库'}
},
{
path: 'outbound/detail/:type(see|add|edit)/:id?',
name: 'purchaseOutboundDetail',
hidden: true,
props: true,
component: () => lazyLoadView(import('@/views/sell/outbound/detail')),
meta: {
title: '销售出库详情',
activeMenu: '/document/outbound/order',
noCache: true,
isDetailPage: true
}
}
]
}

@ -0,0 +1,28 @@
import Vue from "vue"
const state = {
map: {}
}
const mutations = {
init(state, key) {
if (state.map.hasOwnProperty(key)) {
state.map[key] = false
}
else Vue.set(state.map, key, false)
},
emit(state, key) {
state.map[key] = true
},
renew(state, key) {
state.map[key] = false
}
}
export default {
namespaced: true,
state,
mutations
}

@ -239,6 +239,3 @@ function isCyclic(data) {
return detect(data)
}

@ -0,0 +1,9 @@
import {isEmpty} from "@/utils"
import router from '@/router'
import store from '@/store'
export function closeCurrentPage(next) {
return store
.dispatch('tagsView/delView', router.currentRoute)
.then(() => !isEmpty(next) && router.replace(next))
}

@ -49,24 +49,24 @@
</el-row>
</el-card>
<dialog-form v-model="dialog" :loading="false" title="封装的dialog">
<form-dialog v-model="dialog" :loading="false" title="封装的dialog">
<p v-for="i in 50" :key="i">超出部分滚动...</p>
<template v-slot:footer>
<el-button plain size="small" @click="dialog=false"> </el-button>
<el-button size="small" type="primary" @click="dialog=false"> </el-button>
</template>
</dialog-form>
</form-dialog>
</div>
</template>
<script>
import AbstractTable from '@/components/AbstractTable'
import LinerProgress from '@/components/LinerProgress'
import DialogForm from "@/components/DialogForm"
import FormDialog from "@/components/FormDialog"
export default {
name: "stylePage",
components: {AbstractTable, LinerProgress, DialogForm},
components: {AbstractTable, LinerProgress, FormDialog},
data() {
return {
dialog: false,

@ -1,56 +1,46 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" width="50%" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
size="small"
status-icon
>
<el-row :gutter="20">
<dialog-form-item label="标 题:" prop="title" dense>
<el-input v-model="form.title" maxlength="100" :readonly="!canSave"/>
</dialog-form-item>
<dialog-form-item label="消息类型:" prop="type" dense>
<el-select v-model="form.type" :disabled="!canSave">
<el-option :value="0" label="通知提醒"/>
<el-option :value="1" label="系统公告"/>
</el-select>
</dialog-form-item>
<dialog-form-item v-if="type!=='add'" label="创建人:" dense>
<el-input :value="form.cname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="type!=='add'" label="创建时间:" dense>
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="通知对象:" prop="broadcast" dense>
<el-select v-model="form.broadcast" :disabled="!canSave">
<el-option :value="0" label="指定用户"/>
<el-option :value="1" label="全体用户"/>
</el-select>
</dialog-form-item>
<dialog-form-item v-if="form.broadcast===0" label="选择用户:" prop="recipient" dense>
<user-selector v-model="form.recipient" :disabled="!canSave"/>
</dialog-form-item>
<dialog-form-item v-if="form.pname" label="发布人:" dense>
<el-input :value="form.pname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.ptime" label="发布时间:" dense>
<el-date-picker :value="form.ptime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="撤回人:" dense>
<el-input :value="form.wname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="撤回时间:" dense>
<el-date-picker :value="form.wtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="内 容:" full>
<tinymce-editor v-model="form.content" :readonly="!canSave"/>
</dialog-form-item>
</el-row>
</el-form>
<form-dialog :loading="loading" :title="title" :value="value" width="50%" @close="cancel" @open="open">
<abstract-form :model="form" :rules="rules">
<abstract-form-item label="标 题:" prop="title" dense>
<el-input v-model="form.title" maxlength="100" :readonly="!canSave"/>
</abstract-form-item>
<abstract-form-item label="消息类型:" prop="type" dense>
<el-select v-model="form.type" :disabled="!canSave">
<el-option :value="0" label="通知提醒"/>
<el-option :value="1" label="系统公告"/>
</el-select>
</abstract-form-item>
<abstract-form-item v-if="type!=='add'" label="创建人:" dense>
<el-input :value="form.cname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="type!=='add'" label="创建时间:" dense>
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item label="通知对象:" prop="broadcast" dense>
<el-select v-model="form.broadcast" :disabled="!canSave">
<el-option :value="0" label="指定用户"/>
<el-option :value="1" label="全体用户"/>
</el-select>
</abstract-form-item>
<abstract-form-item v-if="form.broadcast===0" label="选择用户:" prop="recipient" dense>
<user-selector v-model="form.recipient" :disabled="!canSave"/>
</abstract-form-item>
<abstract-form-item v-if="form.pname" label="发布人:" dense>
<el-input :value="form.pname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="form.ptime" label="发布时间:" dense>
<el-date-picker :value="form.ptime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item v-if="form.status===2" label="撤回人:" dense>
<el-input :value="form.wname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="form.status===2" label="撤回时间:" dense>
<el-date-picker :value="form.wtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item label="内 容:" full>
<tinymce-editor v-model="form.content" :readonly="!canSave"/>
</abstract-form-item>
</abstract-form>
<template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button>
@ -58,12 +48,13 @@
<el-button v-if="canPublish" size="small" type="primary" @click="publish"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import DialogFormItem from "@/components/DialogForm/DialogFormItem"
import AbstractForm from "@/components/AbstractForm"
import AbstractFormItem from "@/components/AbstractForm/AbstractFormItem"
import FormDialog from '@/components/FormDialog'
import TinymceEditor from "@/components/TinymceEditor"
import {SimpleMultipleUserSelector as UserSelector} from '@/bizComponents/UserSelector'
import dialogMixin from "@/mixins/dialogMixin"
@ -77,7 +68,7 @@
mixins: [dialogMixin],
components: {DialogForm, DialogFormItem, TinymceEditor, UserSelector},
components: {AbstractForm,AbstractFormItem,FormDialog, TinymceEditor, UserSelector},
props: {
value: {type: Boolean, default: false},

@ -1,168 +0,0 @@
<template>
<dialog-form :loading="loading" :value="value" width="70%" @close="cancel" @open="open">
<template slot="title">
{{title}}
<document-history :data="history" :type="type" @show="getHistory"/>
</template>
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
size="small"
status-icon
>
<el-row :gutter="20">
<dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/>
</dialog-form-item>
<dialog-form-item label="采购订单:" prop="pid">
<el-input :value="form.pid" readonly>
<el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button>
</el-input>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="附 件:" full>
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</dialog-form-item>
<dialog-form-item label="备 注:" prop="remark" full>
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</dialog-form-item>
</el-row>
</el-form>
<el-table :data="form.data">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/>
<el-table-column align="center" label="入库数量" width="150">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
@change="(nv,ov)=>changeInboundNum(nv,ov,row)"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
</el-table>
<document-steps :status="form.status" :type="type"/>
<template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
<order-selector v-model="parentDialog" @select="selectParent"/>
</dialog-form>
</template>
<script>
import OrderSelector from "./OrderSelector"
import bizDocumentDialogMixin from "@/mixins/bizDocumentDialogMixin"
import {add, commit, getById, pass, reject, update, withdraw} from "@/api/document/purchase/inbound"
import {getSubById as getParentSubById} from "@/api/document/purchase/order"
import {isEmpty} from "@/utils"
import {isInteger} from "@/utils/validate"
import {elAlert} from "@/utils/message"
export default {
name: "EditDialog",
mixins: [bizDocumentDialogMixin],
components: {OrderSelector},
data() {
return {
documentName: '采购入库单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
pid: null
},
rules: {
pid: [{required: true, message: '请选择采购订单', trigger: 'change'}]
},
parentDialog: false,
parentSubList: []
}
},
methods: {
afterInit() {
if (this.type !== 'edit') return
return getParentSubById(this.form.pid).then(data => this.parentSubList = data)
},
selectParent(id, sub) {
this.parentSubList = sub
this.form.pid = id
this.form.data = sub.map(i => ({
pid: this.form.id,
cid: i.cid,
cname: i.cname,
num: i.remain_num
}))
},
changeInboundNum(nv, ov, row) {
let parentSub = this.parentSubList.find(i => i.cid === row.cid)
if (!parentSub || nv > parentSub.remain_num) {
return elAlert(`${row.cname}的入库数量超出采购数量`, () => row.num = ov)
}
},
validate() {
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
if (this.form.data.length <= 0) return '入库商品不能为空'
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.num)) return `${index}个商品数量不能为空`
if (sub.num < 0 || !isInteger(sub.num)) return `${index}个商品数量有误`
let parentSub = this.parentSubList.find(i => i.cid === sub.cid)
if (!parentSub) return `${index}个商品不在采购订单中`
if (parentSub.remain_num < sub.num) return `${index}个商品的入库数量超出采购数量`
index++
}
return null
}
}
}
</script>

@ -0,0 +1,185 @@
<template>
<div v-loading="loading" class="detail-page">
<doc-detail-header
:title="this.title"
:description="headerDescription"
:extra="headerExtra"
@close="close"
/>
<abstract-form :model="form" :rules="rules">
<el-card header="流程进度">
<doc-steps :status="form.status" :type="type"/>
</el-card>
<el-card header="基础信息">
<abstract-form-item label="采购订单:" prop="pid">
<el-input v-if="canSave" :value="form.pid" readonly>
<el-button slot="append" @click="parentDialog=true">选择</el-button>
</el-input>
<template v-else>{{form.pid}}</template>
</abstract-form-item>
</el-card>
<el-card header="入库商品">
<abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/>
<el-table-column align="center" label="入库数量" width="150">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
@change="(nv,ov)=>changeInboundNum(nv,ov,row)"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
</abstract-table>
</el-card>
<el-card header="附件">
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</el-card>
<el-card header="备注">
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</el-card>
</abstract-form>
<doc-history :id="form.id"/>
<doc-detail-footer>
<template v-slot:right>
<el-button plain size="small" @click="close"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
</doc-detail-footer>
<order-selector v-model="parentDialog" @select="selectParent"/>
</div>
</template>
<script>
import OrderSelector from './components/OrderSelector'
import bizDocDetailMixin from "@/mixins/bizDocDetailMixin"
import {baseUrl, add, commit, getById, pass, reject, update, withdraw} from "@/api/document/purchase/inbound"
import {getSubById as getParentSubById} from "@/api/document/purchase/order"
import {isEmpty} from "@/utils"
import {isInteger} from "@/utils/validate"
import {elAlert} from "@/utils/message"
import {timestamp2Date} from "@/filter"
export default {
name: "purchaseInboundDetail",
mixins: [bizDocDetailMixin],
components: {OrderSelector},
data() {
return {
baseUrl,
docName: '采购入库单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
pid: null
},
rules: {
pid: [{required: true, message: '请选择采购订单', trigger: 'change'}]
},
parentDialog: false,
parentSubList: []
}
},
computed: {
headerDescription() {
return [
{label: '创建人:', content: this.form.cname},
{label: '创建时间:', content: timestamp2Date(this.form.ctime)},
{label: '审核人:', content: this.form.vname},
{label: '审核时间:', content: timestamp2Date(this.form.vtime)}
]
},
headerExtra() {
return [
{title: '单据状态', content: this.getStatus(this.form.status)}
]
}
},
methods: {
afterInit() {
if (this.type !== 'edit') return
return getParentSubById(this.form.pid).then(data => this.parentSubList = data)
},
selectParent(id, sub) {
this.parentSubList = sub
this.form.pid = id
this.form.data = sub.map(i => ({
pid: this.form.id,
cid: i.cid,
cname: i.cname,
num: i.remain_num
}))
},
changeInboundNum(nv, ov, row) {
let parentSub = this.parentSubList.find(i => i.cid === row.cid)
if (!parentSub || nv > parentSub.remain_num) {
return elAlert(`${row.cname}的入库数量超出采购数量`, () => row.num = ov)
}
},
validate() {
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
if (this.form.data.length <= 0) {
return '入库商品不能为空'
}
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.num)) {
return `${index}个商品数量不能为空`
}
if (sub.num < 0 || !isInteger(sub.num)) {
return `${index}个商品数量有误`
}
let parentSub = this.parentSubList.find(i => i.cid === sub.cid)
if (!parentSub) {
return `${index}个商品不在采购订单中`
}
if (parentSub.remain_num < sub.num) {
return `${index}个商品的入库数量超出采购数量`
}
index++
}
return null
}
}
}
</script>

@ -92,34 +92,25 @@
@current-change="pageChange"
/>
</el-row>
<edit-dialog
v-model="editDialog"
:base-url="baseUrl"
:id="row?row.id:null"
:type.sync="type"
@search="search"
/>
</el-card>
</template>
<script>
import EditDialog from './components/EditDialog'
import SearchForm from '@/components/SearchForm'
import SearchFormItem from "@/components/SearchForm/SearchFormItem"
import documentTableMixin from '@/mixins/bizDocumentTableMixin'
import {del, getSubById, search} from "@/api/document/purchase/inbound"
import {baseUrl,del, getSubById, search} from "@/api/document/purchase/inbound"
export default {
name: "purchaseInbound",
mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem},
components: {SearchForm, SearchFormItem},
data() {
return {
baseUrl: '/purchase/inbound',
baseUrl,
api: {search, del, getSubById},
searchForm: {
pid_fuzzy: null

@ -1,211 +0,0 @@
<template>
<dialog-form :loading="loading" :value="value" width="70%" @close="cancel" @open="open">
<template v-slot:title>
{{title}}
<document-history :data="history" :type="type" @show="getHistory"/>
</template>
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
size="small"
status-icon
>
<el-row :gutter="20">
<dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/>
</dialog-form-item>
<dialog-form-item label="供应商:" prop="sname">
<el-input :value="form.sname" readonly>
<el-button slot="append" :disabled="!canSave" @click="supplierDialog=true">选择</el-button>
</el-input>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.finish===2" label="完成时间:" prop="ftime">
<el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="附 件:" full>
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</dialog-form-item>
<dialog-form-item label="备 注:" prop="remark" full>
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</dialog-form-item>
</el-row>
</el-form>
<el-table ref="table" :data="form.data">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品">
<template v-slot="{row}">
<category-selector
v-if="row._editable"
v-model="row.cid"
:selected="selectedCategories"
@get-name="row.cname=$event"
/>
<span v-else>{{row.cname}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="采购数量">
<template v-slot="{row}">
<el-input-number
v-if="row._editable"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="采购单价">
<template v-slot="{row}">
<el-input-number
v-if="row._editable"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column v-if="form.id" align="center" label="剩余未入库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="入库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部入库':'未全部入库'}}
</template>
</el-table-column>
<el-table-column v-if="canSave" align="center" label="操作" width="140">
<template v-if="canSave" v-slot="{row,$index}">
<el-button v-if="!row._editable" type="text" @click="()=>row._editable=true">编辑</el-button>
<el-button v-else type="text" @click="()=>row._editable=false">保存</el-button>
<el-button type="text" @click="()=>delSub(row,$index)">删除</el-button>
</template>
</el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button plain type="dashed" size="small" icon="el-icon-plus" @click="addSub">添加采购商品</el-button>
</div>
</el-table>
<document-steps :status="form.status" :type="type"/>
<template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span>
<span v-if="form.finish===2" class="seal">已完成</span>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
<supplier-selector v-model="supplierDialog" @select="selectSupplier" @jump="closeDialog"/>
</dialog-form>
</template>
<script>
import SupplierSelector from './SupplierSelector'
import CategorySelector from './CategorySelector'
import bizDocumentDialogMixin from "@/mixins/bizDocumentDialogMixin"
import {add, commit, getById, pass, reject, update, withdraw} from "@/api/document/purchase/order"
import {isEmpty} from "@/utils"
import {plus, mul} from "@/utils/math"
import {isInteger} from "@/utils/validate"
export default {
name: "EditDialog",
mixins: [bizDocumentDialogMixin],
components: {CategorySelector, SupplierSelector},
data() {
return {
documentName: '采购订单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
sid: null,
sname: null,
finish: 0,
ftime: null,
total: 0
},
rules: {
sname: [{required: true, message: '供应商不能为空', trigger: 'change'}]
},
supplierDialog: false
}
},
computed: {
selectedCategories() {
return this.form.data.map(i => i.cid)
}
},
methods: {
selectSupplier(row) {
this.form.sid = row.id
this.form.sname = row.name
},
addSub() {
this.form.data.push({
cid: null,
cname: null,
num: 0,
price: 0,
_editable: true
})
},
delSub(row, index) {
this.form.data.splice(index, 1)
},
validate() {
if (this.form.data.length <= 0) return '采购商品不能为空'
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.cid, sub.cname)) return `${index}个商品分类不能为空`
if (isEmpty(sub.num)) return `${index}个商品数量不能为空`
if (isEmpty(sub.price)) return `${index + 1}个商品单价不能为空`
if (sub.num < 0 || !isInteger(sub.num)) return `${index}个商品数量有误`
if (sub.price <= 0 || !isInteger(sub.price)) return `${index}个商品单价有误`
this.form.total = plus(this.form.total, mul(sub.num, sub.price))
index++
}
return null
},
afterInit() {
this.form.data.forEach(item => item.__editable = false)
}
}
}
</script>

@ -0,0 +1,241 @@
<template>
<div v-loading="loading" class="detail-page">
<doc-detail-header
:title="this.title"
:description="headerDescription"
:extra="headerExtra"
@close="close"
/>
<abstract-form :model="form" :rules="rules">
<el-card header="流程进度">
<doc-steps :status="form.status" :finish="form.finish" :type="type"/>
</el-card>
<el-card header="基础信息">
<abstract-form-item label="供应商:" prop="sname">
<el-input v-if="canSave" :value="form.sname" readonly>
<el-button slot="append" @click="supplierDialog=true">选择</el-button>
</el-input>
<template v-else>{{form.sname}}</template>
</abstract-form-item>
</el-card>
<el-card header="采购商品">
<abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品">
<template v-slot="{row}">
<category-selector
v-if="row._editable"
v-model="row.cid"
:selected="selectedCategories"
@get-name="row.cname=$event"
/>
<span v-else>{{row.cname}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="采购数量">
<template v-slot="{row}">
<el-input-number
v-if="row._editable"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="采购单价">
<template v-slot="{row}">
<el-input-number
v-if="row._editable"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column v-if="form.id" align="center" label="剩余未入库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="入库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部入库':'未全部入库'}}
</template>
</el-table-column>
<el-table-column v-if="canSave" align="center" label="操作" width="140">
<template v-if="canSave" v-slot="{row,$index}">
<el-button v-if="!row._editable" type="text" @click="()=>row._editable=true">编辑</el-button>
<el-button v-else type="text" @click="()=>row._editable=false">保存</el-button>
<el-button type="text" @click="()=>delSub(row,$index)">删除</el-button>
</template>
</el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button
plain
type="dashed"
icon="el-icon-plus"
:disabled="!canAddSub"
@click="addSub"
>
添加采购商品
</el-button>
</div>
</abstract-table>
</el-card>
<el-card header="附件">
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</el-card>
<el-card header="备注">
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</el-card>
</abstract-form>
<doc-history :id="form.id"/>
<doc-detail-footer>
<template v-slot:right>
<el-button plain size="small" @click="close"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
</doc-detail-footer>
<supplier-selector v-model="supplierDialog" @select="selectSupplier"/>
</div>
</template>
<script>
import CategorySelector from './components/CategorySelector'
import SupplierSelector from './components/SupplierSelector'
import bizDocDetailMixin from "@/mixins/bizDocDetailMixin"
import {baseUrl, add, commit, getById, pass, reject, update, withdraw} from "@/api/document/purchase/order"
import {isEmpty} from "@/utils"
import {isInteger} from "@/utils/validate"
import {mul, plus} from "@/utils/math"
import {timestamp2Date} from "@/filter"
export default {
name: "purchaseOrderDetail",
mixins: [bizDocDetailMixin],
components: {CategorySelector, SupplierSelector},
data() {
return {
baseUrl,
docName: '采购订单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
sid: null,
sname: null,
finish: 0,
ftime: null,
total: 0
},
rules: {
sname: [{required: true, message: '供应商不能为空', trigger: 'change'}]
},
supplierDialog: false
}
},
computed: {
headerDescription() {
return [
{label: '创建人:', content: this.form.cname},
{label: '创建时间:', content: timestamp2Date(this.form.ctime)},
{label: '审核人:', content: this.form.vname},
{label: '审核时间:', content: timestamp2Date(this.form.vtime)},
{label: '完成时间:', content: timestamp2Date(this.form.ftime)}
]
},
headerExtra() {
return [
{title: '单据状态', content: this.getStatus(this.form.status)},
{title: '完成情况', content: this.getFinish(this.form.finish)}
]
},
selectedCategories() {
return this.form.data.map(i => i.cid)
},
canAddSub() {
return this.form.data.every(i => !i._editable)
}
},
methods: {
selectSupplier(row) {
this.form.sid = row.id
this.form.sname = row.name
},
addSub() {
this.form.data.push({
cid: null,
cname: null,
num: 0,
price: 0,
_editable: true
})
},
delSub(row, index) {
this.form.data.splice(index, 1)
},
validate() {
if (this.form.data.length <= 0) {
return '采购商品不能为空'
}
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.cid, sub.cname)) {
return `${index}个商品分类不能为空`
}
if (isEmpty(sub.num)) {
return `${index}个商品数量不能为空`
}
if (isEmpty(sub.price)) {
return `${index + 1}个商品单价不能为空`
}
if (sub.num < 0 || !isInteger(sub.num)) {
return `${index}个商品数量有误`
}
if (sub.price <= 0 || !isInteger(sub.price)) {
return `${index}个商品单价有误`
}
this.form.total = plus(this.form.total, mul(sub.num, sub.price))
index++
}
return null
},
afterInit() {
this.form.data.forEach(item => item.__editable = false)
}
}
}
</script>

@ -55,6 +55,7 @@
/>
</search-form-item>
</search-form>
<el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
@ -64,6 +65,7 @@
<el-button v-if="canExport" icon="el-icon-download" size="small" type="info" @click="downloadExcel">
</el-button>
</el-row>
<el-row v-loading="config.loading" class="table-container">
<abstract-table
:data="tableData"
@ -118,31 +120,22 @@
@current-change="pageChange"
/>
</el-row>
<edit-dialog
v-model="editDialog"
:base-url="baseUrl"
:id="row?row.id:null"
:type.sync="type"
@search="search"
/>
</el-card>
</template>
<script>
import EditDialog from './components/EditDialog'
import SearchForm from '@/components/SearchForm'
import SearchFormItem from "@/components/SearchForm/SearchFormItem"
import documentTableMixin from '@/mixins/bizDocumentTableMixin'
import {del, getSubById, search} from "@/api/document/purchase/order"
import {baseUrl, del, getSubById, search} from "@/api/document/purchase/order"
export default {
name: "purchaseOrder",
mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem},
components: {SearchForm, SearchFormItem},
data() {
return {
baseUrl: '/purchase/order',
baseUrl,
searchForm: {
sname: null
},

@ -13,15 +13,6 @@
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button
v-if="canGoToSysCustomerPage"
plain
size="small"
type="dashed"
@click="goToSysCustomerPage"
>
添加客户
</el-button>
</el-row>
<el-scrollbar>
@ -65,7 +56,6 @@
import tableMixin from '@/mixins/tablePageMixin'
import {getCustomers} from "@/api/system/customer"
import {elError} from "@/utils/message"
import {auth} from "@/utils/auth"
export default {
name: "CustomerSelector",
@ -84,12 +74,6 @@
}
},
computed: {
canGoToSysCustomerPage() {
return auth('/system/customer')
}
},
methods: {
search() {
if (!this.value || this.config.loading) return
@ -116,12 +100,6 @@
cancel() {
this.closeDialog()
this.tableData = []
},
goToSysCustomerPage() {
this.closeDialog()
this.$emit('jump')
this.$nextTick(() => this.$router.push('/system/customer'))
}
}
}

@ -1,216 +0,0 @@
<template>
<dialog-form :loading="loading" :value="value" width="70%" @close="cancel" @open="open">
<template v-slot:title>
{{title}}
<document-history :data="history" :type="type" @show="getHistory"/>
</template>
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
size="small"
status-icon
>
<el-row :gutter="20">
<dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/>
</dialog-form-item>
<dialog-form-item label="客 户:" prop="customer_name">
<el-input :value="form.customer_name" readonly>
<el-button slot="append" :disabled="!canSave" @click="customerDialog=true">选择</el-button>
</el-input>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.finish===2" label="完成时间:" prop="ftime">
<el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="附 件:" full>
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</dialog-form-item>
<dialog-form-item label="备 注:" prop="remark" full>
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</dialog-form-item>
</el-row>
</el-form>
<el-table ref="table" :data="form.data">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商品" prop="cname"/>
<el-table-column align="center" label="销售数量">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="销售单价">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="剩余未出库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="出库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部出库':'未全部出库'}}
</template>
</el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button
plain
type="dashed"
size="small"
icon="el-icon-plus"
@click="stockDialog=true"
>
添加销售商品
</el-button>
</div>
</el-table>
<document-steps :status="form.status" :type="type"/>
<template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span>
<span v-if="form.finish===2" class="seal">已完成</span>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
<stock-selector v-model="stockDialog" @select="selectStock"/>
<customer-selector v-model="customerDialog" @select="selectCustomer" @jump="closeDialog"/>
</dialog-form>
</template>
<script>
import StockSelector from './StockSelector'
import CustomerSelector from './CustomerSelector'
import bizDocumentDialogMixin from "@/mixins/bizDocumentDialogMixin"
import {add, commit, getById, pass, reject, update, withdraw} from "@/api/document/sell/order"
import {isEmpty} from "@/utils"
import {mul, plus} from "@/utils/math"
import {isInteger} from "@/utils/validate"
export default {
name: "EditDialog",
mixins: [bizDocumentDialogMixin],
components: {StockSelector, CustomerSelector},
data() {
return {
documentName: '销售订单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
customer_id: null,
customer_name: null,
finish: 0,
ftime: null,
total: 0
},
rules: {
customer_name: [{required: true, message: '客户不能为空', trigger: 'change'}]
},
customerDialog: false,
stockDialog: false
}
},
computed: {
selectedCategories() {
return this.form.data.map(i => i.cid)
}
},
methods: {
selectCustomer(row) {
this.form.customer_id = row.id
this.form.customer_name = row.name
this.customerDialog = false
},
selectStock(stocks) {
this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.total_num, price: 0}))
this.stockDialog = false
},
addSub() {
this.form.data.push({
cid: null,
cname: null,
num: 0,
price: 0,
remain_num: 0
})
},
delSub(row, index) {
this.form.data.splice(index, 1)
},
validate() {
if (this.form.data.length <= 0) return '销售商品不能为空'
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.cid, sub.cname)) return `${index}个商品分类不能为空`
if (isEmpty(sub.num)) return `${index}个商品数量不能为空`
if (isEmpty(sub.price)) return `${index + 1}个商品单价不能为空`
if (sub.num < 0 || !isInteger(sub.num)) return `${index}个商品数量有误`
if (sub.price <= 0 || !isInteger(sub.price)) return `${index}个商品单价有误`
this.form.total = plus(this.form.total, mul(sub.num, sub.price))
index++
}
return null
}
}
}
</script>

@ -0,0 +1,217 @@
<template>
<div v-loading="loading" class="detail-page">
<doc-detail-header
:title="this.title"
:description="headerDescription"
:extra="headerExtra"
@close="close"
/>
<abstract-form :model="form" :rules="rules">
<el-card header="流程进度">
<doc-steps :status="form.status" :type="type"/>
</el-card>
<el-card header="基础信息">
<abstract-form-item label="客 户:" prop="customer_name">
<el-input v-if="canSave" :value="form.customer_name" readonly>
<el-button slot="append" @click="customerDialog=true">选择</el-button>
</el-input>
<template v-else>{{form.customer_name}}</template>
</abstract-form-item>
</el-card>
<el-card header="销售商品">
<abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商品" prop="cname"/>
<el-table-column align="center" label="销售数量">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="销售单价">
<template v-slot="{row}">
<el-input-number
v-if="canSave"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="剩余未出库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="出库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部出库':'未全部出库'}}
</template>
</el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button
plain
type="dashed"
icon="el-icon-plus"
:disabled="!canAddSub"
@click="stockDialog=true"
>
添加销售商品
</el-button>
</div>
</abstract-table>
</el-card>
<el-card header="附件">
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</el-card>
<el-card header="备注">
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</el-card>
</abstract-form>
<doc-history :id="form.id"/>
<doc-detail-footer>
<template v-slot:right>
<el-button plain size="small" @click="close"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
</doc-detail-footer>
<stock-selector v-model="stockDialog" @select="selectStock"/>
<customer-selector v-model="customerDialog" @select="selectCustomer"/>
</div>
</template>
<script>
import CustomerSelector from './components/CustomerSelector'
import StockSelector from './components/StockSelector'
import bizDocDetailMixin from "@/mixins/bizDocDetailMixin"
import {baseUrl, add, commit, getById, pass, reject, update, withdraw} from "@/api/document/sell/order"
import {isEmpty} from "@/utils"
import {mul, plus} from "@/utils/math"
import {isInteger} from "@/utils/validate"
import {timestamp2Date} from "@/filter"
export default {
name: "sellOrderDetail",
mixins: [bizDocDetailMixin],
components: {CustomerSelector, StockSelector},
data() {
return {
baseUrl,
docName: '销售订单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
form: {
customer_id: null,
customer_name: null,
finish: 0,
ftime: null,
total: 0
},
rules: {
customer_name: [{required: true, message: '客户不能为空', trigger: 'change'}]
},
customerDialog: false,
stockDialog: false
}
},
computed: {
headerDescription() {
return [
{label: '创建人:', content: this.form.cname},
{label: '创建时间:', content: timestamp2Date(this.form.ctime)},
{label: '审核人:', content: this.form.vname},
{label: '审核时间:', content: timestamp2Date(this.form.vtime)},
{label: '完成时间:', content: timestamp2Date(this.form.ftime)}
]
},
headerExtra() {
return [
{title: '单据状态', content: this.getStatus(this.form.status)},
{title: '完成情况', content: this.getFinish(this.form.finish)}
]
},
selectedCategories() {
return this.form.data.map(i => i.cid)
},
canAddSub() {
return this.form.data.every(i => !i._editable)
}
},
methods: {
selectCustomer(row) {
this.form.customer_id = row.id
this.form.customer_name = row.name
this.customerDialog = false
},
selectStock(stocks) {
this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.total_num, price: 0}))
this.stockDialog = false
},
addSub() {
this.form.data.push({
cid: null,
cname: null,
num: 0,
price: 0,
remain_num: 0
})
},
delSub(row, index) {
this.form.data.splice(index, 1)
},
validate() {
if (this.form.data.length <= 0) return '销售商品不能为空'
if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试'
}
let index = 1
for (let sub of this.form.data) {
if (isEmpty(sub.cid, sub.cname)) return `${index}个商品分类不能为空`
if (isEmpty(sub.num)) return `${index}个商品数量不能为空`
if (isEmpty(sub.price)) return `${index + 1}个商品单价不能为空`
if (sub.num < 0 || !isInteger(sub.num)) return `${index}个商品数量有误`
if (sub.price <= 0 || !isInteger(sub.price)) return `${index}个商品单价有误`
this.form.total = plus(this.form.total, mul(sub.num, sub.price))
index++
}
return null
}
}
}
</script>

@ -124,34 +124,25 @@
@current-change="pageChange"
/>
</el-row>
<edit-dialog
v-model="editDialog"
:base-url="baseUrl"
:id="row?row.id:null"
:type.sync="type"
@search="search"
/>
</el-card>
</template>
<script>
import EditDialog from './components/EditDialog'
import SearchForm from '@/components/SearchForm'
import SearchFormItem from "@/components/SearchForm/SearchFormItem"
import documentTableMixin from '@/mixins/bizDocumentTableMixin'
import {del, getSubById, search} from "@/api/document/sell/order"
import {baseUrl, del, getSubById, search} from "@/api/document/sell/order"
export default {
name: "sellOrder",
mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem},
components: {SearchForm, SearchFormItem},
data() {
return {
baseUrl: '/sell/order',
baseUrl,
searchForm: {
customer_name: null
},

@ -1,132 +1,123 @@
<template>
<dialog-form :loading="loading" :value="value" width="70%" @close="cancel" @open="open">
<template slot="title">
{{title}}
<document-history :data="history" :type="type" @show="getHistory"/>
</template>
<div v-loading="loading" class="detail-page">
<doc-detail-header
:title="this.title"
:description="headerDescription"
:extra="headerExtra"
@close="close"
/>
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
size="small"
status-icon
>
<el-row :gutter="20">
<dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/>
</dialog-form-item>
<dialog-form-item label="销售订单:" prop="pid">
<el-input :value="form.pid" readonly>
<el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button>
<abstract-form :model="form" :rules="rules">
<el-card header="流程进度">
<doc-steps :status="form.status" :finish="form.finish" :type="type"/>
</el-card>
<el-card header="基础信息">
<abstract-form-item label="销售订单:" prop="pid">
<el-input v-if="canSave" :value="form.pid" readonly>
<el-button slot="append" @click="parentDialog=true">选择</el-button>
</el-input>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/>
</dialog-form-item>
<dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item>
<dialog-form-item label="附 件:" full>
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</dialog-form-item>
<dialog-form-item label="备 注:" prop="remark" full>
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</dialog-form-item>
</el-row>
</el-form>
<template v-else>{{form.pid}}</template>
</abstract-form-item>
</el-card>
<el-table :data="displayTableData">
<el-table-column align="center" type="expand">
<el-table slot-scope="{row}" :data="row.data" border show-summary :summary-method="summaryStock(row)">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center">
<template slot="header">
出库数量
<el-button v-if="canSave" type="text" size="small" @click="openStock(row)">选择库存</el-button>
</template>
<template v-slot="d">
<el-input-number
v-if="canSave"
v-model="d.row.num"
controls-position="right"
:min="0"
size="small"
@change="(nv,ov)=>changeOutboundNum(nv,ov,d.row,row)"
/>
<span v-else>{{d.row.num}}</span>
</template>
<el-card header="出库商品">
<abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" type="expand">
<el-table slot-scope="{row}" :data="row.data" border show-summary :summary-method="summaryStock(row)">
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center">
<template slot="header">
出库数量
<el-button v-if="canSave" type="text" size="small" @click="openStock(row)">选择库存</el-button>
</template>
<template v-slot="d">
<el-input-number
v-if="canSave"
v-model="d.row.num"
controls-position="right"
:min="0"
size="small"
@change="(nv,ov)=>changeOutboundNum(nv,ov,d.row,row)"
/>
<span v-else>{{d.row.num}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="采购订单" prop="cgddid" show-overflow-tooltip/>
<el-table-column align="center" label="采购入库" prop="cgrkid" show-overflow-tooltip/>
</el-table>
</el-table-column>
<el-table-column align="center" label="采购订单" prop="cgddid" show-overflow-tooltip/>
<el-table-column align="center" label="采购入库" prop="cgrkid" show-overflow-tooltip/>
</el-table>
</el-table-column>
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/>
<el-table-column align="center" label="出库数量" prop="num" width="150"/>
<el-table-column align="center" label="订单剩余未出库数量" prop="remain_num" width="250"/>
</el-table>
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/>
<el-table-column align="center" label="出库数量" prop="num" width="150"/>
<el-table-column align="center" label="订单剩余未出库数量" prop="remain_num" width="250"/>
</abstract-table>
</el-card>
<el-card header="附件">
<upload-file
:file-list="form.imageList"
:disabled="!canSave"
@remove="removeUpload"
@success="uploadSuccess"
/>
</el-card>
<el-card header="备注">
<el-input
v-model="form.remark"
:rows="4"
:readonly="!canSave"
maxlength="200"
show-word-limit
type="textarea"
/>
</el-card>
</abstract-form>
<document-steps :status="form.status" :type="type"/>
<doc-history :id="form.id"/>
<template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
<doc-detail-footer>
<template v-slot:right>
<el-button plain size="small" @click="close"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
<el-button v-if="canCommit" size="small" type="primary" @click="commit"> </el-button>
<el-button v-if="canWithdraw" size="small" type="danger" @click="withdraw"> </el-button>
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template>
</doc-detail-footer>
<order-selector v-model="parentDialog" @select="selectParent"/>
<stock-selector v-model="stockDialog" :cid="row?row.cid:null" @select="selectStock"/>
</dialog-form>
</div>
</template>
<script>
import OrderSelector from "./OrderSelector"
import StockSelector from "./StockSelector"
import bizDocumentDialogMixin from "@/mixins/bizDocumentDialogMixin"
import OrderSelector from "./components/OrderSelector"
import StockSelector from "./components/StockSelector"
import bizDocDetailMixin from "@/mixins/bizDocDetailMixin"
import {getDetailById as getStockDetail} from "@/api/stock/current"
import {getSubById as getParentSubById} from "@/api/document/sell/order"
import {add, commit, getById, pass, reject, update, withdraw} from "@/api/document/sell/outbound"
import {baseUrl, add, commit, getById, pass, reject, update, withdraw} from "@/api/document/sell/outbound"
import {isEmpty} from "@/utils"
import {plus, sub} from "@/utils/math"
import {isInteger} from "@/utils/validate"
import {elAlert} from "@/utils/message"
import {timestamp2Date} from "@/filter"
export default {
name: "EditDialog",
name: "sellOutboundDetail",
mixins: [bizDocumentDialogMixin],
mixins: [bizDocDetailMixin],
components: {OrderSelector, StockSelector},
data() {
return {
documentName: '销售出库单',
baseUrl,
docName: '销售出库单',
api: {
getById, add, update, commit, withdraw, pass, reject
},
@ -143,6 +134,22 @@
}
},
computed: {
headerDescription() {
return [
{label: '创建人:', content: this.form.cname},
{label: '创建时间:', content: timestamp2Date(this.form.ctime)},
{label: '审核人:', content: this.form.vname},
{label: '审核时间:', content: timestamp2Date(this.form.vtime)}
]
},
headerExtra() {
return [
{title: '单据状态', content: this.getStatus(this.form.status)}
]
}
},
methods: {
afterInit() {
if (this.type === 'add') return

@ -96,34 +96,25 @@
@current-change="pageChange"
/>
</el-row>
<edit-dialog
v-model="editDialog"
:base-url="baseUrl"
:id="row?row.id:null"
:type.sync="type"
@search="search"
/>
</el-card>
</template>
<script>
import EditDialog from './components/EditDialog'
import SearchForm from '@/components/SearchForm'
import SearchFormItem from "@/components/SearchForm/SearchFormItem"
import documentTableMixin from '@/mixins/bizDocumentTableMixin'
import {del, getSubById, search} from "@/api/document/sell/outbound"
import {baseUrl, del, getSubById, search} from "@/api/document/sell/outbound"
export default {
name: "sellOutbound",
mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem},
components: {SearchForm, SearchFormItem},
data() {
return {
baseUrl: '/sell/outbound',
baseUrl,
api: {search, del, getSubById},
searchForm: {
pid_fuzzy: null

@ -1,5 +1,5 @@
<template>
<dialog-form :value="value" :loading="false" :title="title" width="70%" @close="cancel" @open="search">
<form-dialog :value="value" :loading="false" :title="title" width="70%" @close="cancel" @open="search">
<liner-progress :show="loading"/>
<abstract-table :data="tableData" border show-summary :summary-method="summary" :span-method="span">
@ -28,13 +28,13 @@
<el-table-column align="center" label="库存数量" prop="num" show-overflow-tooltip/>
<el-table-column align="center" label="总 值" prop="total" show-overflow-tooltip/>
</abstract-table>
</dialog-form>
</form-dialog>
</template>
<script>
import AbstractTable from '@/components/AbstractTable'
import LinerProgress from '@/components/LinerProgress'
import DialogForm from "@/components/DialogForm"
import FormDialog from "@/components/FormDialog"
import dialogMixin from "@/mixins/dialogMixin"
import {isEmpty} from "@/utils"
import {plus, mul} from "@/utils/math"
@ -45,7 +45,7 @@
mixins: [dialogMixin],
components: {AbstractTable, LinerProgress, DialogForm},
components: {AbstractTable, LinerProgress, FormDialog},
props: {value: Boolean, title: String, cid: Number},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -50,11 +50,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import RegionSelector from '@/components/RegionSelector'
import dialogMixin from "@/mixins/dialogMixin"
import {addCustomer, updateCustomer} from "@/api/system/customer"
@ -66,7 +66,7 @@
mixins: [dialogMixin],
components: {DialogForm, RegionSelector},
components: {FormDialog, RegionSelector},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -26,11 +26,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {addDepartment, updateDepartment} from "@/api/system/department"
import {isEmpty} from '@/utils'
@ -41,7 +41,7 @@
mixins: [dialogMixin],
components: {DialogForm},
components: {FormDialog},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" title="编辑" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" title="编辑" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -38,11 +38,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {updateResource} from "@/api/system/resource"
import {mergeObj, resetObj} from '@/utils'
@ -52,7 +52,7 @@
mixins: [dialogMixin],
components: {DialogForm},
components: {FormDialog},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -44,11 +44,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {addRole, updateRole} from "@/api/system/role"
import {isEmpty, mergeObj} from '@/utils'
@ -59,7 +59,7 @@
mixins: [dialogMixin],
components: {DialogForm},
components: {FormDialog},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -50,11 +50,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import RegionSelector from '@/components/RegionSelector'
import dialogMixin from "@/mixins/dialogMixin"
import {addSupplier, updateSupplier} from "@/api/system/supplier"
@ -66,7 +66,7 @@
mixins: [dialogMixin],
components: {DialogForm, RegionSelector},
components: {FormDialog, RegionSelector},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
@ -30,11 +30,11 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import RoleSelector from './RoleSelector'
import dialogMixin from "@/mixins/dialogMixin"
import {checkName} from "@/api/account"
@ -47,7 +47,7 @@
mixins: [dialogMixin],
components: {DialogForm, RoleSelector},
components: {FormDialog, RoleSelector},
props: {
value: {type: Boolean, default: false},

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" title="修改密码" :value="value" width="30%" @close="cancel">
<form-dialog :loading="loading" title="修改密码" :value="value" width="30%" @close="cancel">
<el-form
ref="form"
:model="form"
@ -21,12 +21,12 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import md5 from "js-md5"
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {updateUserPwd} from "@/api/account"
import {elSuccess} from "@/utils/message"
@ -34,7 +34,7 @@
export default {
mixins: [dialogMixin],
components: {DialogForm},
components: {FormDialog},
data() {
return {

@ -1,5 +1,5 @@
<template>
<dialog-form :loading="loading" title="上传头像" :value="value" width="50%" @close="cancel">
<form-dialog :loading="loading" title="上传头像" :value="value" width="50%" @close="cancel">
<el-row class="avatar-cropper">
<div class="img-wrapper">
<vue-cropper
@ -30,12 +30,12 @@
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</dialog-form>
</form-dialog>
</template>
<script>
import {VueCropper} from 'vue-cropper'
import DialogForm from '@/components/DialogForm'
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {elError, elSuccess} from "@/utils/message"
import {autoCompleteUrl, upload} from "@/utils/file"
@ -46,7 +46,7 @@
mixins: [dialogMixin],
components: {VueCropper, DialogForm},
components: {VueCropper, FormDialog},
props: {
value: Boolean

Loading…
Cancel
Save