editcopy.vue 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. <template>
  2. <div>
  3. <Toptitle :title='$route.query.type == 1 ? "新增订单" : "编辑订单"'>
  4. <Button @click="back" type='primary' ghost style="margin-right:10px;">返回</Button>
  5. <Button @click="showForms = true" type='primary' style="margin-right:10px;">表单设置</Button>
  6. <Button type="primary" @click="handleSubmit('infoOrder')">保存</Button>
  7. </Toptitle>
  8. <div class="page-edit">
  9. <!-- 表单项 -->
  10. <Form ref='infoOrder' inline :label-width="100" :model="info" style="padding:10px 0;" :rules="infoRules">
  11. <FormItem v-if='formObjs.renovation_type' label="订单类型:" prop='renovation_type'>
  12. <RadioGroup v-model="info.renovation_type" class="auto-width">
  13. <Radio :label="1">楼栋(工装)</Radio>
  14. <Radio :label="2">单户(家装)</Radio>
  15. </RadioGroup>
  16. </FormItem>
  17. <FormItem v-if='formObjs.order_no' label="订单编号:">
  18. <Input disabled v-model="info.order_no" class="auto-width" placeholder="自动生成"/>
  19. </FormItem>
  20. <FormItem v-if='formObjs.residential_name' label="项目名称:" prop='residential_name'>
  21. <Input v-model="info.residential_name" class="auto-width" placeholder="请输入项目名称"/>
  22. </FormItem>
  23. <FormItem v-if='formObjs.client_name' label="客户姓名:">
  24. <Input v-model="info.client_name" class="auto-width" placeholder="请输入客户姓名"/>
  25. </FormItem>
  26. <FormItem v-if='formObjs.warning_state' label="紧急程度:" prop='warning_state'>
  27. <Select clearable class="auto-width" v-model="info.warning_state">
  28. <Option label='不急' :value='0'></Option>
  29. <Option label='比较急' :value='1'></Option>
  30. <Option label='紧急' :value='2'></Option>
  31. <Option label='非常急' :value='3'></Option>
  32. </Select>
  33. </FormItem>
  34. <FormItem v-if='formObjs.salesman' label="业务员:">
  35. <Select clearable filterable v-model="info.salesman" class="auto-width">
  36. <Option v-for="item of users" :key="item.id" :label="item.nickname" :value="item.id"></Option>
  37. </Select>
  38. </FormItem>
  39. <FormItem v-if='formObjs.pay_state' label="收款:">
  40. <RadioGroup v-model="info.pay_state" class="auto-width">
  41. <Radio :label="0">未收款</Radio>
  42. <Radio :label="1">已收款</Radio>
  43. </RadioGroup>
  44. </FormItem>
  45. <FormItem v-if='formObjs.address' label="详细地址:">
  46. <Input v-model="info.address" class="auto-width" placeholder="请输入项目名称"/>
  47. </FormItem>
  48. <FormItem v-if='formObjs.mobile' label="手机号:" prop='mobile'>
  49. <Input v-model="info.mobile" class="auto-width" placeholder="请输入手机号"/>
  50. </FormItem>
  51. <FormItem v-if='formObjs.start_time' label="开始日期:" prop='start_time'>
  52. <DatePicker v-model="info.start_time" type="date" placeholder="开始日期" class="auto-width"></DatePicker>
  53. </FormItem>
  54. <FormItem v-if='formObjs.end_time' label="交付日期:" prop='end_time'>
  55. <DatePicker v-model="info.end_time" type="date" placeholder="交付日期" class="auto-width"></DatePicker>
  56. </FormItem>
  57. <FormItem v-if='formObjs.predict_price' label="产品总价:">
  58. <Input disabled v-model="info.predict_price" class="auto-width" placeholder="自动生成"/>
  59. </FormItem>
  60. <FormItem v-if='formObjs.predict_working' label="预估工期:">
  61. <Input disabled v-model="info.predict_working" class="auto-width" placeholder="自动生成"/>
  62. </FormItem>
  63. <FormItem v-if='formObjs.predict_time' label="预估交付日期:">
  64. <Input disabled v-model="info.predict_time" class="auto-width" placeholder="自动生成"/>
  65. </FormItem>
  66. <FormItem v-if='formObjs.remark' label="订单备注:">
  67. <Input v-model="info.remark" class="auto-width" placeholder="请输入订单备注"/>
  68. </FormItem>
  69. </Form>
  70. <!-- 户型选择 -->
  71. <div class="items" v-for="(item,index) of info.house" :key="index">
  72. <div class="items-header">
  73. <div class="header-left">
  74. <Badge :count="index+1" type="primary"></Badge>
  75. <span>户型{{index+1}}</span>
  76. </div>
  77. <div class="header-right" v-if="info.renovation_type == 1">
  78. <Button type="success" style="margin-right:10px;" ghost shape="circle" @click="addHours(info.house)">添加</Button>
  79. <Button type="success" style="margin-right:10px;" ghost shape="circle" @click="copyHours(info.house,item)">复制</Button>
  80. <Button v-if="info.house.length!=1" type="error" ghost shape="circle" @click="delItems(info.house,index)">删除</Button>
  81. </div>
  82. </div>
  83. <div class="form-item">
  84. <Form inline :label-width="80">
  85. <FormItem label="楼幢(楼号)" v-if='info.renovation_type != 2'>
  86. <Input v-model="item.house" placeholder="请输入楼幢(楼号)"/>
  87. </FormItem>
  88. <FormItem label="楼单元" v-if='info.renovation_type != 2'>
  89. <Input v-model="item.unit" placeholder="请输入楼单元"/>
  90. </FormItem>
  91. <FormItem label="楼层" v-if='info.renovation_type != 2'>
  92. <Input v-model="item.layer" placeholder="请输入楼层"/>
  93. </FormItem>
  94. <FormItem label="房间号" v-if='info.renovation_type != 2'>
  95. <Input v-model="item.number" placeholder="请输入房间号"/>
  96. </FormItem>
  97. <FormItem label="选择产品">
  98. <Button @click="selectProducts(1,item)" type="primary" style="margin-right:10px;" ghost>选择产品</Button>
  99. </FormItem>
  100. </Form>
  101. </div>
  102. <div class="items-table">
  103. <Table :style="'width:'+tableWidth+'px'" border :columns="item.product_top" :data="item.product">
  104. <template slot='url' slot-scope='{row}'>
  105. <div>
  106. <img style="max-width:50px;max-height:50px;" v-if="row.url" :src="$store.state.ip+row.url" alt="">
  107. </div>
  108. </template>
  109. <template slot='drawing' slot-scope='{row}'>
  110. <div>
  111. <img style="max-width:30px;max-height:30px;" v-if="row.drawing" :src="$store.state.ip+row.drawing" alt="">
  112. </div>
  113. </template>
  114. <template slot='set' slot-scope='{index}'>
  115. <div class="table-set">
  116. <svg style="font-size:20px" color='#3764FF' @click="selectProducts(2,item,index)" class="icon icon-nav" aria-hidden="true">
  117. <use xlink:href="#iconbianji"></use>
  118. </svg>
  119. <svg style="font-size:20px" color='green' @click="selectProducts(3,item,index)" class="icon icon-nav" aria-hidden="true">
  120. <use xlink:href="#iconxiangqing"></use>
  121. </svg>
  122. <svg v-if="item.product.length>1" @click="delItems(item.product,index)" class="icon icon-nav" style="font-size:20px" color='red' aria-hidden="true">
  123. <use xlink:href="#iconshanchu"></use>
  124. </svg>
  125. </div>
  126. </template>
  127. </Table>
  128. </div>
  129. </div>
  130. <!-- 原材料 -->
  131. <div class="original-part">
  132. <Table border :span-method="handleSpan" :columns="originalTableColumns" :data="originalData"></Table>
  133. </div>
  134. </div>
  135. <!-- 选择产品弹层 -->
  136. <Modal :width="1200" class-name="vertical-center-modal" title="选择产品" v-model="showProduct" @on-visible-change='modalVisibleChange'>
  137. <div class="nav-product">
  138. <Tag type="border" v-for="(item,idx) in modalArray" :key="idx">
  139. <a @click="jump('#product_'+idx)" >{{item.title}}</a>
  140. </Tag>
  141. </div>
  142. <div class="modal-scroll">
  143. <div class="modal-items" :id="'product_'+idx" v-for="(item,idx) in modalArray" :key="idx">
  144. <Form inline :model="item" :rules="productRules" ref='productModel'>
  145. <FormItem label="选择产品" prop='product_id'>
  146. <Select filterable clearable label-in-value size='small' :disabled='productType == 3 ? true : false' v-model="item.product_id" @on-change='changeProduct($event,idx)' style="width:186px;">
  147. <Option v-for="item of productList" :tag='item.img_url' :key="item.id" :label="item.title" :value='item.id'></Option>
  148. </Select>
  149. </FormItem>
  150. <FormItem label="位置" prop='position'>
  151. <Input size='small' :disabled='productType == 3 ? true : false' v-model="item.position" placeholder="请输入位置"/>
  152. </FormItem>
  153. <FormItem label="计量单位">
  154. <Input size='small' disabled v-model="item.unit" placeholder="请输入计量单位"/>
  155. </FormItem>
  156. <FormItem v-if='item.same_process' label="工艺属性">
  157. <div style="display:flex;width:100%;position:relative;top:5px;">
  158. <Select @on-change="changeProcess($event,item.parts,vc,idx)" v-for="(same_process,vc) of item.same_process" :key="same_process.id" v-model="same_process.select_id" size='small'>
  159. <Option v-for='same_item of same_process.option' :key='same_item.id' :label="same_item.title" :value="same_item.id"></Option>
  160. </Select>
  161. </div>
  162. </FormItem>
  163. <FormItem v-for="(measuring,measuring_key) in item.measuring" :label="measuring.title" :key="measuring_key+11">
  164. <Input @on-blur="blurMeasur(item,idx)" :disabled='productType == 3 ? true : false' :placeholder="'请输入'+measuring.title" size='small' v-model="item[measuring.key]"/>
  165. </FormItem>
  166. <FormItem v-for="(remake,remake_key) in item.product_remake" :label="remake.title" :key="remake_key+31">
  167. <Input placeholder="请输入" size='small' v-model="item[remake.title]"/>
  168. </FormItem>
  169. <FormItem label="议价(元)">
  170. <Input @on-blur="changePrice(item,2,$event)" type="number" size='small' :disabled='productType == 3 ? true : false' v-model="item.real_price" placeholder="请输入议价"/>
  171. </FormItem>
  172. <FormItem label='产品价格'>
  173. <Input size='small' disabled v-model="item.price" placeholder="自动生成"/>
  174. </FormItem>
  175. <FormItem label="附加价格">
  176. <Input @on-blur="changePrice(item,1,$event)" type="number" size='small' :disabled='productType == 3 ? true : false' v-model="item.attach_price" placeholder="请输入议价"/>
  177. </FormItem>
  178. <FormItem v-for="(outh,outh_key) in item.outh" :label="outh.title" :key="outh_key+21">
  179. <img v-if="outh.key=='img'||outh.key=='url'" @click="showPreview(item,outh.key)" style="max-width:30px;max-height:30px;top:5px;position:relative;cursor:pointer;" :src="$store.state.ip+outh.value">
  180. <Input v-if="outh.key!='img'&&outh.key!='url'&&outh.key!='lock'" disabled placeholder="自动生成" size='small' v-model="outh.value"/>
  181. <Select label-in-value @on-change="changeLock($event,item,idx)" size="small" clearable style="width:186px;" v-if="outh.key=='lock'" v-model="item[outh.key]">
  182. <Option v-for="luck of lock_list" :key='luck.id' :tag='luck.price' :value="luck.id" :label="luck.title"></Option>
  183. <Option :value="0" label="无"></Option>
  184. </Select>
  185. </FormItem>
  186. <FormItem label='备注'>
  187. <Input size='small' v-model="item.remake" placeholder="请输入备注"/>
  188. </FormItem>
  189. </Form>
  190. <Button size='small' type="primary" style="margin-bottom:10px;" @click="resetShowTable(item)">{{item.showTable ? '收起' : '定制'}}</Button>
  191. <Table v-if="item.showTable" stripe border :columns="parts_Columns" :data="item.parts">
  192. <template slot='ProcessCombination' slot-scope="{row}">
  193. <div>
  194. {{row.process_attribute}}
  195. </div>
  196. </template>
  197. <template slot='Costum' slot-scope="{row}">
  198. <div>
  199. <span v-for="(column,_key) of row.custom_route" :key="column.id">{{column.title+(_key==row.custom_route.length-1 ? '' : '/')}}</span>
  200. </div>
  201. </template>
  202. <template slot='set' slot-scope='{row,index}'>
  203. <div>
  204. <Poptip :ref='"popTip"+idx+index' placement="left-start" @on-popper-hide='popperHide'>
  205. <Button type='primary' size='small'>自定义工艺属性</Button>
  206. <div slot="content">
  207. <div class="hierarchy" v-for="(item,keys) of coumstList" :key="item.id">
  208. <span>{{item.name||item.title}}(单选):</span>
  209. <div class="radio-g">
  210. <div @click="setRadioChange(item,_item,keys)" :class="['radio-us',_item.show ? 'radio-us-foc' : '']" v-for='_item of item.cld' :key="_item.id">{{_item.title}}</div>
  211. </div>
  212. </div>
  213. <div class="pop-footer">
  214. <Button @click="cancelCoustom(index,idx)" style='margin-right:10px'>取消</Button>
  215. <Button @click="saveCosutom(row,index,item,idx)" style='margin-left:10px' type='primary'>确定</Button>
  216. </div>
  217. </div>
  218. </Poptip>
  219. </div>
  220. </template>
  221. </Table>
  222. <div class="modal-footer-button">
  223. <Button @click="copyProduct(modalArray,idx)" type="warning" style="margin-right:10px;" ghost shape="circle">复制产品</Button>
  224. <Button @click="addParts(item)" type="success" style="margin-right:10px;" ghost shape="circle">添加</Button>
  225. <Button v-if='modalArray.length!=1' @click="delItems(modalArray,idx)" type="error" ghost shape="circle">删除</Button>
  226. </div>
  227. </div>
  228. </div>
  229. <div slot="footer">
  230. <Button @click="cancelModal">取消</Button>
  231. <Button @click="handleProductSubmit('productModel')" type="primary">确定</Button>
  232. </div>
  233. </Modal>
  234. <Modal v-model="showForms" @on-ok="postForms(1)" class-name="vertical-center-modal" title='表单设置'>
  235. <CheckboxGroup v-model="forms_list">
  236. <Checkbox label="renovation_type">订单类型</Checkbox>
  237. <Checkbox label="order_no">订单编号</Checkbox>
  238. <Checkbox label="residential_name">项目名称</Checkbox>
  239. <Checkbox label="client_name">客户姓名</Checkbox>
  240. <Checkbox label="warning_state">紧急程度</Checkbox>
  241. <Checkbox label="salesman">业务员</Checkbox>
  242. <Checkbox label="pay_state">收款</Checkbox>
  243. <Checkbox label="address">详细地址</Checkbox>
  244. <Checkbox label="mobile">手机号</Checkbox>
  245. <Checkbox label="start_time">开始日期</Checkbox>
  246. <Checkbox label="end_time">交付日期</Checkbox>
  247. <Checkbox label="predict_price">产品总价</Checkbox>
  248. <Checkbox label="predict_working">预估工期</Checkbox>
  249. <Checkbox label="predict_time">预估交付日期</Checkbox>
  250. <Checkbox label="remark">订单备注</Checkbox>
  251. </CheckboxGroup>
  252. </Modal>
  253. </div>
  254. </template>
  255. <script>
  256. export default {
  257. data(){
  258. const validateMobile = function(rule,value,fn){
  259. if(!(/^1[3456789]\d{9}$/.test(value))){
  260. fn(new Error(' '))
  261. return false
  262. }
  263. fn()
  264. };
  265. return {
  266. formObjs:{
  267. renovation_type:1,
  268. order_no:1,
  269. residential_name:1,
  270. client_name:1,
  271. warning_state:1,
  272. salesman:1,
  273. pay_state:1,
  274. address:1,
  275. mobile:1,
  276. start_time:1,
  277. end_time:1,
  278. predict_price:1,
  279. predict_working:1,
  280. predict_time:1,
  281. remark:1,
  282. },
  283. formObjs_reset:{
  284. renovation_type:1,
  285. order_no:1,
  286. residential_name:1,
  287. client_name:1,
  288. warning_state:1,
  289. salesman:1,
  290. pay_state:1,
  291. address:1,
  292. mobile:1,
  293. start_time:1,
  294. end_time:1,
  295. predict_price:1,
  296. predict_working:1,
  297. predict_time:1,
  298. remark:1,
  299. },
  300. showForms:false,
  301. forms_list:[],
  302. type:1,
  303. id:this.$route.query.id,
  304. modalArray:[],
  305. productList:[],
  306. coumstList:[],
  307. tableWidth:null,
  308. currentIndex:null,
  309. proxyObj:{},
  310. _proxyObj:{},
  311. productType:1,
  312. watchComputed:null,
  313. users:[],
  314. coustomArray:[],
  315. lock_list:[],
  316. showProcessAttrabut:false,
  317. headers:{'Authorization':localStorage.getItem('token')},
  318. originalTableColumns:[
  319. {title:'原材料名称',align:'center',key:'title'},
  320. {title:'原材料库存',align:'center',key:'stock'},
  321. {title:'所需原材料数量',align:'center',key:'num'},
  322. {title:'原材料单价',align:'center',key:'price'},
  323. {title:'规格型号',align:'center',key:'specifications'},
  324. {title:'原材料单位',align:'center',key:'unit'},
  325. {title:'原材料预估费用',align:'center',key:'num_price'},
  326. ],
  327. Top:[],
  328. parts_Columns:[
  329. {title:'部件',key:'title',align:'center'},
  330. {title:'工艺组合名称',key:'ProcessCombination',align:'center',minWidth:100},
  331. {title:'自定义组合名称',key:'',align:'center',slot:'Costum',minWidth:100},
  332. {title:'指导报价',key:'price',align:'center'},
  333. {title:'部件测量数据',key:'measur',align:'center'},
  334. {title:'预估工时',key:'maber_time',align:'center',
  335. render:(h,params)=>h('span',{},`${params.row.maber_time}小时`)
  336. },
  337. {title:'操作',key:'title',align:'center',slot:'set'},
  338. ],
  339. originalData:[],
  340. tableColumns:[
  341. {title:'产品类型',align:'center',key:'product_type',minWidth:100,fixed:'left'},
  342. {title:'产品名称',align:'center',key:'title',minWidth:150},
  343. {title:'产品型号',align:'center',key:'model',minWidth:100},
  344. {title:'测量数据',align:'center',key:'measure',minWidth:100},
  345. {title:'位置',align:'center',key:'position',minWidth:100},
  346. {title:'图纸',align:'center',minWidth:80,key:'url',slot:'url'},
  347. {title:'图号',align:'center',key:'url_number',minWidth:150},
  348. {title:'议价(元)',align:'center',key:'real_price',minWidth:100},
  349. {title:'预估工时',align:'center',key:'limit_time',minWidth:200},
  350. {title:'操作',align:'center',slot:'set',fixed:'right',width:'150'},
  351. ],
  352. tableData:[],
  353. showProduct:false,
  354. infoRules:{
  355. residential_name:[{required: true,message:' ',trigger:'blur'}],
  356. client_name:[{required: true,message:' ',trigger:'blur'}],
  357. warning_state:[{required: true,message:' '}],
  358. pay_state:[{required: true,message:'请选择'}],
  359. address:[{required: true,message:' ',trigger:'blur'}],
  360. mobile:[{required: true,validator: validateMobile, trigger: 'blur'}],
  361. start_time:[{required: true,message:' '}],
  362. end_time:[{required: true,message:' '}],
  363. renovation_type:[{required: true,message:'请选择订单类型'}]
  364. },
  365. productRules:{
  366. position:[{required: true,message:' ',trigger:'blur'}],
  367. real_price:[{required: true,message:' ',}],
  368. product_id:[{required: true,message:' ',}]
  369. },
  370. info:{
  371. residential_name:'',//项目名称
  372. order_no:'',//订单号
  373. renovation_type:1,//订单类型
  374. client_name:'',//客户名称
  375. address:'',//
  376. mobile:'',//手机号
  377. start_time:new Date().toLocaleDateString().replace(/\//g,"-"),//开始时间
  378. end_time:'',//结束时间
  379. pay_state:'',//是否支付
  380. warning_state:0,//是否紧急
  381. predict_time:'',//预估交付日期
  382. salesman:this.$store.state.userInfo.id||null,//业务员
  383. predict_price:null,//预估工价,
  384. predict_working:null,//预估工期
  385. remark:'',
  386. house:[
  387. {
  388. house:null,
  389. unit:null,
  390. layer:null,
  391. number:null,
  392. product_top:[],
  393. product:[
  394. {
  395. product_id:null,
  396. attach_price:0,
  397. product_name:'',
  398. measure:'',
  399. price:'',
  400. real_price:'',
  401. type:null,
  402. unit:'',
  403. img:'',
  404. drawing:'',
  405. model:'',
  406. url_number:'',
  407. url:'',
  408. route_id:'',
  409. limit_time:null,
  410. parts:[],
  411. showTable:false,
  412. }
  413. ],
  414. },
  415. ]
  416. },
  417. }
  418. },
  419. watch:{
  420. 'info.renovation_type':{
  421. handler(e){
  422. if(e == 2){
  423. this.info.house.map(v=>{
  424. v.house = '1';
  425. v.layer = '1';
  426. v.unit = '1';
  427. v.number = '1';
  428. })
  429. }
  430. }
  431. }
  432. },
  433. created(e){
  434. this.tableWidth = window.innerWidth-300;
  435. this.getUsers()
  436. this.type = this.$route.query.type
  437. this.axios('/api/order_get_forms').then(res=>{
  438. if(res.code == 200){
  439. this.forms_list = res.data
  440. this.postForms(0)
  441. }
  442. })
  443. this.getCoumstList()
  444. this.getLockList()
  445. },
  446. mounted(){
  447. if(this.id){
  448. if(this.id){
  449. this.info = {}
  450. }
  451. this.getDate(this.id)
  452. }
  453. this.getProducts()
  454. addEventListener('resize',(e)=>{
  455. this.tableWidth = e.target.innerWidth - 300;
  456. this.$forceUpdate()
  457. })
  458. },
  459. methods:{
  460. back(){
  461. this.$router.go(-1)
  462. },
  463. postForms(n){
  464. let result = []
  465. this.forms_list.map(rows=>{
  466. for(let i in this.formObjs_reset){
  467. if(i == rows){
  468. result.push(i)
  469. }
  470. }
  471. })
  472. const news_forms = {}
  473. result.forEach(element=>{
  474. news_forms[element] = 1
  475. })
  476. this.formObjs = news_forms
  477. if(n){
  478. this.axios.post('/api/order_set_form',{result:this.forms_list,all:Object.keys(this.formObjs_reset)}).then(res=>{
  479. if(res.code == 200){
  480. this.$Message.success(res.msg)
  481. }
  482. })
  483. }
  484. },
  485. postData(){
  486. let sendData = JSON.parse(JSON.stringify(this.info));
  487. let op = this.type == 1 ? 'add' : 'edit';
  488. try{
  489. sendData.start_time = new Date(sendData.start_time).toLocaleDateString().replace(/\//g,"-")
  490. sendData.end_time = new Date(sendData.end_time).toLocaleDateString().replace(/\//g,"-")
  491. }catch(e){}
  492. let params = {op:op,detail:sendData}
  493. this.axios.post('/api/order_save',params).then(res=>{
  494. if(res.code == 200){
  495. this.$Message.success(res.msg)
  496. this.back()
  497. }
  498. })
  499. },
  500. getDate(id){
  501. this.axios('/api/order_detail',{params:{id:id}}).then(res=>{
  502. res.data.predict_working = `${(res.data.predict_working/8).toFixed(1)}天`
  503. this.info = res.data;
  504. this.forms_list = res.tableSet||[]
  505. this.tapProduct()
  506. })
  507. },
  508. selectProducts(n,row,q){
  509. this.productType = n;
  510. this.showProduct = true;
  511. this.proxyObj = row;
  512. this.modalArray = JSON.parse(JSON.stringify(row.product)) || [];
  513. },
  514. delItems(row,n){
  515. row.splice(n,1)
  516. try{
  517. row[n].product_id ? this.tapProduct() : ''
  518. }catch(e){}
  519. },
  520. addHours(row){
  521. row.push({
  522. house:null,
  523. unit:null,
  524. layer:null,
  525. number:null,
  526. product:[{product_id:''}],
  527. })
  528. },
  529. getProducts(){
  530. this.axios('/api/product').then(res=>this.productList = res.data.data)
  531. },
  532. changeProduct(row,n,ext){
  533. let id = row ? row.value : this.productList[0].id
  534. this.axios('/api/order_product_detail',{params:{id:id}}).then(res=>{
  535. let _this = this;
  536. let modalData = this.modalArray[n]
  537. modalData.product_type = res.data.detail.product_type||''
  538. modalData.unit = res.data.detail.unit||''
  539. modalData.model = res.data.detail.model || ''
  540. modalData.price = modalData.price ? modalData.price : 0;
  541. res.data.outh.map(v=>{
  542. if(v.key == 'img'){
  543. modalData.img = v.value
  544. }
  545. })
  546. if(res.code == 200){
  547. if(!ext){
  548. if(row){modalData.title = row.label||''}
  549. modalData.measuring = res.data.measuring;
  550. modalData.outh = res.data.outh;
  551. modalData.product_remake = res.data.product_remake;
  552. }
  553. let result = res.data.intermediate.same_process[0].reduce((pre,cur)=>{
  554. return pre.concat([{option:[],select_id:null}])
  555. },[])
  556. // let result = [{option:[],select_id:null},{option:[],select_id:null},{option:[],select_id:null}]
  557. res.data.intermediate.same_process.map((cur)=>{
  558. cur.forEach((i,index)=>{
  559. try{
  560. const curIdx = result[index].option.findIndex(q=>i.id == q.id)
  561. curIdx<0 ? result[index].option.push(i) : ''
  562. }catch(e){
  563. console.log('数据异常')
  564. }
  565. })
  566. })
  567. modalData.parts = res.data.intermediate.parts
  568. result.forEach((element,index)=>{
  569. element.select_id = element.option.length == 1 ? element.option[0].id : ''
  570. element.title = element.option.length == 1 ? element.option[0].title : ''
  571. if(element.select_id){
  572. this.changeProcess(element.select_id,modalData.parts,index,n)
  573. }
  574. })
  575. modalData.same_process = result;
  576. modalData.parts.map(v=>{
  577. v.process_ids = v.process_ids || []
  578. v.maber_time = v.maber_time || 0
  579. v.price = v.price || 0
  580. v.measur = v.measur || 0;
  581. v.route_list.map(q=>q.select=false)
  582. })
  583. this.Top = res.data.product_top;
  584. const index = this.Top.findIndex(v=>v.key == 'img')
  585. this.Top[index] = {...this.Top[index],render:(h,params)=>h('img',{
  586. attrs:{
  587. src:_this.$store.state.ip+params.row.img||'',
  588. style:'max-width:30px;max-height:30px;'
  589. }
  590. },)}
  591. this.Top.forEach(element=>{
  592. if(element.key == 'drawing'){
  593. modalData.drawing = element.value
  594. }
  595. })
  596. this.$forceUpdate()
  597. }
  598. })
  599. },
  600. addParts(row){
  601. this.modalArray.push({
  602. product_id:null,
  603. product_name:'',
  604. drawing:'',
  605. attach_price:0,
  606. measure:'',
  607. price:'0',
  608. real_price:'',
  609. type:null,
  610. unit:'',
  611. img:'',
  612. model:'',
  613. url_number:'',
  614. url:'',
  615. route_id:'',
  616. limit_time:null,
  617. parts:[],
  618. showTable:false,
  619. process_attributes:''
  620. })
  621. },
  622. saveParts(){
  623. this.modalArray.map(v=>{//计算预估工期,指导报价
  624. v.process = v.same_process.reduce((pre,cur,n)=>{
  625. if(cur.title){
  626. return `${pre}${cur.title}${n == v.same_process.length-1 ? '' : '/'}`
  627. }else{
  628. cur.option.forEach(element=>cur.select_id == element.id ? cur.title = element.title : '')
  629. return `${pre}${cur.title}${n == v.same_process.length-1 ? '' : '/'}`
  630. }
  631. },'')
  632. try{
  633. v.limit_time = v.parts.reduce((pre,cur)=>pre+Number(cur.maber_time),0)
  634. v.price = v.parts.reduce((pre,cur)=>pre+cur.price*1||0,0)
  635. if(v.measure){
  636. v.measure = v.measure.reduce((pre,cur)=>pre+=(cur+=(v[cur]||'')+'*'),'')
  637. v.measure = v.measure.substr(0,v.measure.length-1,'')
  638. }else{
  639. v.measure = v.measuring.reduce((pre,cur,n)=>`${pre}${n == 0 ? '' : '*'}${cur.key}`,'')
  640. }
  641. }catch(e){}
  642. })
  643. this.proxyObj.product = this.modalArray;
  644. if(this.Top.length>0){
  645. this.proxyObj.product_top = this.Top;
  646. }
  647. this.proxyObj.product_top.map(v=>{v.width=200,v.align = 'center'})
  648. const {house} = this.info
  649. const predict_time_array = house.reduce((pre,cur)=>pre.concat(cur.product),[])
  650. this.info.predict_working = predict_time_array.reduce((pre,cur)=>{
  651. return pre+=cur.limit_time
  652. },0)
  653. this.info.predict_working = `${(this.info.predict_working/8).toFixed(1)}天`
  654. this.$forceUpdate()
  655. this.tapProduct()
  656. this.showProduct = false;
  657. },
  658. cancelModal(){
  659. this.modalArray = [{}]
  660. this.showProduct = false;
  661. },
  662. handleSubmit(name) {
  663. this.$refs[name].validate((valid) => {
  664. if(valid){
  665. this.postData()
  666. }
  667. })
  668. },
  669. handleProductSubmit(name){
  670. const result = []
  671. for(let i = 0;i<this.$refs[name].length;i++){
  672. this.$refs[name][i].validate((valid) => result.push(valid))
  673. }
  674. const flag = result.every(row=>row)
  675. if(flag){this.saveParts()}
  676. },
  677. tapProduct(){
  678. let product_id = '';
  679. let measure = '';
  680. let house = ''
  681. this.info.house.map(v=>{
  682. product_id += v.product.reduce((pre,cur,index)=>pre+=(cur.product_id+'|'+(String(v.house).split(',').length||1)*(String(v.unit).split(',').length||1)*(String(v.layer).split(',').length||1)*(String(v.number).split(',').length||1)+','),'')
  683. measure += v.product.reduce((pre,cur,index)=>pre+=(cur.measure+','),'')
  684. })
  685. product_id = product_id.substr(0,product_id.length-1,'')
  686. const productInfo_arr = product_id.split(',')
  687. let _id = '',_num = ''
  688. productInfo_arr.map((v)=>{
  689. let arr = v.split('|')
  690. _id+=`${arr[0]},`
  691. _num+=`${arr[1]},`
  692. })
  693. measure = measure.substr(0,measure.length-1,'')
  694. _id = _id.substr(0,_id.length-1,'')
  695. _num = _num.substr(0,_num.length-1,'')
  696. house = house.substr(0,house.length-1,'')
  697. this.axios('/api/house_detail_material',{params:{product_id:_id,measure:measure,num:_num}}).then(res=>{
  698. if(res.code == 200){
  699. this.originalData = res.data.data;
  700. this.originalData.push({end:true,stock:res.data.num,title:'合计'})
  701. }
  702. })
  703. },
  704. handleSpan ({ row, column, rowIndex, columnIndex }) {
  705. if(row.end){
  706. return [1,6]
  707. }
  708. },
  709. mapRow(n){
  710. this.currentIndex = n;
  711. },
  712. successUpload(responce){
  713. let url = responce.data.url;
  714. this.modalArray[this.currentIndex].url = url
  715. },
  716. getUsers(){
  717. this.axios('/api/user',{params:{type:1}}).then(res=>this.users = res.data.data)
  718. },
  719. getCoumstList(){
  720. this.axios('/api/bpp_list').then(res=>{
  721. res.data.map(v=>{
  722. if(v.select){
  723. v.cld.map(z=>{
  724. v.select.map(k=>{
  725. z.show = k == z.id ? true : false
  726. })
  727. })
  728. }else{
  729. v.cld.map(v=>v.show = false)
  730. }
  731. })
  732. this.coumstList = res.data;
  733. })
  734. },
  735. setRadioChange(parent,child,n){
  736. parent.cld.map(v=>v.show = false)
  737. parent.select == child.id ? child.show = true : ''
  738. child.show = true
  739. this.coustomArray[n] = child
  740. parent.select = child.id
  741. this.$forceUpdate()
  742. },
  743. popperHide(e){
  744. this.coustomArray = []
  745. this.getCoumstList()
  746. },
  747. saveCosutom(row,index,item,idx){
  748. row.route_list.map(v=>v.select=false)
  749. row.process_attribute = ''
  750. row.custom_route = JSON.parse(JSON.stringify(this.coustomArray));
  751. row.maber_time = 0;
  752. let removePrice = row.price;
  753. row.price = 0;
  754. this.axios.post('/api/get_process_route',{part_id:row.id,result:this.coustomArray.reduce((pre,cur)=>pre.concat(cur.id),[])}).then(res=>{
  755. if(res.code == 200){
  756. row.router_id = res.data
  757. }
  758. })
  759. this.$refs[('popTip'+idx+index)][0].cancel()
  760. this.modalArray[idx].same_process = null;
  761. this.modalArray[idx].parts[index] = row;
  762. this.modalArray[idx].price = parseInt(this.modalArray[idx].price) - removePrice
  763. this.$forceUpdate()
  764. },
  765. cancelCoustom(index,idx){
  766. this.$refs[('popTip'+idx+index)][0].cancel()
  767. },
  768. blurMeasur(row,idx){
  769. const mapReds = Object.values(row.measuring)
  770. const result = mapReds.reduce((pre,cur)=>pre.concat(cur.key),[])
  771. this.modalArray[idx].measure = result;
  772. this.$forceUpdate()
  773. row.parts.map(v=>{
  774. const asy = result.reduce((pre,cur)=>pre.replace(cur,(cur+=(row[cur]||'0'))),v.formula)
  775. const lettersReg = /[a-z,A-Z]/g
  776. const notLetterReg = /[^a-z,A-Z]/g
  777. let valus = asy.split('*')
  778. let mapresult = ''
  779. valus.map(item=>{
  780. let letters = eval(item.replace(lettersReg,''))
  781. let not_l = item.replace(notLetterReg,'')
  782. mapresult+=`${not_l}${letters}*`
  783. })
  784. v.measur = mapresult.substr(0,mapresult.length-1,'')
  785. })
  786. },
  787. copyProduct(maprows,item){
  788. let rows = JSON.parse(JSON.stringify(maprows[item]));
  789. rows.position = ''
  790. const ms = rows.measuring.map(v=>v.key)
  791. ms.forEach((element) => rows[element] = '')
  792. maprows.push(rows)
  793. },
  794. getLockList(){
  795. this.axios('/api/lock_list').then(res=>this.lock_list = res.data)
  796. },
  797. changeLock(value,row,idx){
  798. if(row.old_lock_price){
  799. row.price = parseInt(row.price) - row.old_lock_price
  800. }
  801. row.old_lock_price = parseInt(value.tag||'0');
  802. row.price = parseInt(row.price)+parseInt(value.tag||'0')
  803. this.modalArray[idx] = row;
  804. this.$forceUpdate()
  805. },
  806. jump(querry){
  807. document.querySelector(querry).scrollIntoView({
  808. behavior: "smooth", // 平滑过渡
  809. block: "start" // 上边框与视窗顶部平齐。默认值
  810. })
  811. },
  812. resetShowTable(row){
  813. row.showTable = !row.showTable
  814. this.$forceUpdate()
  815. },
  816. changeProcess(e,parts,n,idx){
  817. this.modalArray[idx].price = 0;
  818. parts.map(element=>{
  819. if(!element.process_ids){
  820. element.process_ids = []
  821. }
  822. element.process_ids[n] = e
  823. let router_id = element.process_ids.join(',')
  824. if(element.process_ids.length >= 1){//开始匹配工艺路线
  825. element.route_list.map(v=>{
  826. const id = v.pp_ids.join(',')
  827. if(router_id == id){
  828. element.router_id = v.id
  829. element.ProcessCombination = v.title
  830. this.axios('/api/get_route_select',{params:{route_id:element.router_id}})
  831. .then(res=>{
  832. if(res.code == 200){
  833. Object.assign(element,res.data)
  834. this.modalArray[idx].price += Number(res.data.price||0)
  835. this.$forceUpdate()
  836. }
  837. })
  838. }
  839. })
  840. }
  841. })
  842. },
  843. changePrice(row,type,e){
  844. const val = e.target.value
  845. if(val){
  846. if(type == 2){
  847. if(row.price){
  848. row.attach_price = row.real_price - row.price
  849. }else{
  850. row.attach_price = 0
  851. }
  852. }else{
  853. row.real_price = row.attach_price*1+row.price*1
  854. }
  855. }else{
  856. }
  857. },
  858. showPreview(row,type){
  859. this.axios('/api/orders_img',{params:{id:row.product_id,type:type == 'img' ? 1 : 2}}).then(res=>{
  860. if(res.code == 200){
  861. row.imgs = res.data
  862. this.$previewImg({
  863. list:row.imgs,
  864. baseUrl:this.$store.state.ip,
  865. baseImgField:'img_url',
  866. baseTitleField:''
  867. })
  868. }
  869. })
  870. },
  871. modalVisibleChange(e){
  872. if(!e){
  873. this.cancelModal()
  874. }
  875. },
  876. copyHours(array,row){
  877. array.push(JSON.parse(JSON.stringify(row)))
  878. }
  879. }
  880. }
  881. </script>
  882. <style lang='scss' scoped>
  883. .page-edit{overflow: hidden;overflow-y: auto;position:relative;top:20px;height:85%;padding-bottom: 20px;;}
  884. .auto-width{width:200px;}
  885. .items{box-shadow: 0 2px 7px rgba(0,0,0,.15);border-color: transparent;position: relative;border-radius:5px;margin-top:20px;
  886. .items-header{padding:10px 20px;display:flex;justify-content: space-between;align-items: center;border-bottom:1px solid #F4F4F4;
  887. .header-left{span{margin-left:10px;}}
  888. }
  889. .form-item{padding:20px;}
  890. }
  891. .modal-scroll{height:600px;overflow: scroll;}
  892. .modal-items{border-radius:5px;border:1px solid #DEDEDE;padding:0px 10px;margin-bottom:40px;}
  893. .modal-footer-button{display: flex;justify-content:flex-end;padding:10px 0;}
  894. .items-table{width:100%;overflow-x: scroll;}
  895. /deep/ .ivu-table-wrapper{overflow:visible;color:red;}//穿透iview
  896. .original-part{padding-top:20px;}
  897. .column-li{display: flex;justify-content: space-between;align-items: center;padding: 2px 5px;}
  898. .hierarchy{
  899. .radio-g{padding:10px 0;display:flex;
  900. .radio-us{background: #F4F5F7;;padding:5px 20px;margin-right:18px;color:#999999;border-radius:15px;border:1px solid #DEDEDE;cursor:pointer;}
  901. .radio-us-foc{color:#3764FF;background:#fff;border:1px solid #3764FF;}
  902. }
  903. }
  904. .nav-product{width:100%;height:50px;display: flex;align-items: center;}
  905. </style>