自主产品,供应链食堂系统。将两个端拆开了。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

432 lines
11 KiB

  1. <template>
  2. <view>
  3. <view class="box">
  4. <view class="title">报价清单</view>
  5. <view class="lf-font-24 lf-color-gray lf-m-t-5">请在以下物资信息表内填写报价</view>
  6. </view>
  7. <!-- 修饰条 -->
  8. <self-line></self-line>
  9. <view class="box lf-row-between relation">
  10. <view>
  11. <text class="title">关联食堂</text>
  12. <text class="lf-font-24 lf-color-555 lf-m-l-10">(多选)</text>
  13. </view>
  14. <view class="lf-font-24 lf-color-gray lf-text-right lf-row-center" style="width: 370rpx; justify-content: flex-end;" @click="switchRelation">
  15. <view class="lf-line-1">{{ selectName }}</view>
  16. <u-icon name="arrow-right" class="lf-text-vertical"></u-icon>
  17. </view>
  18. <view class="mask" :style="{top: node_top +'px'}" v-if="is_show" @click="is_show = false">
  19. <view class="list">
  20. <view class="lf-row-between item" v-for="(item, index) in relation_list" :key="index" @click.stop="selectItem(index)">
  21. <view>{{ item.canteen_name }}</view>
  22. <u-icon name="checkmark-circle" color="#1833F2" size="40" v-if="item.checked"></u-icon>
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. <self-line></self-line>
  28. <!-- 物料table -->
  29. <view class="box">
  30. <view class="lf-font-32 lf-color-black lf-font-bold lf-m-b-20">报价明细</view>
  31. <wyb-table :first-line-fixed="true"
  32. contentBgColor="#eef6fe"
  33. :headers="headers"
  34. :contents="contents"
  35. @onInputChange="onInputChange"
  36. @onButtonClick="onButtonClick"
  37. width="100%" height="80vh"></wyb-table>
  38. </view>
  39. <view style="height: 140rpx;"></view>
  40. <!-- 操作按钮 -->
  41. <view class="fixed-bottom">
  42. <button class="btn btn1" @click="save(0)">临时保存</button>
  43. <button class="btn btn2" @click="save(1)">直接报价</button>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. import wybTable from '@/components/wyb-table/wyb-table';
  49. let app = getApp();
  50. export default {
  51. components: {
  52. wybTable
  53. },
  54. data(){
  55. return {
  56. headers: [{
  57. label: '物资名称',
  58. key: 'name'
  59. },{
  60. label: '规格',
  61. key: 'spec'
  62. },{
  63. label: '单位',
  64. key: 'unit'
  65. },{
  66. label: '分类',
  67. key: 'category'
  68. },{
  69. label: '品牌',
  70. key: 'brand'
  71. },{
  72. label: '品级',
  73. key: 'quality_level'
  74. },{
  75. label: '编号',
  76. key: 'number'
  77. },{
  78. label: '起购数',
  79. key: 'purchase_limit'
  80. },{
  81. label: '含税价',
  82. key: 'tax_price'
  83. },{
  84. label: '非含税价',
  85. key: 'non_tax_price'
  86. },{
  87. label: '操作',
  88. key: 'operation'
  89. }],
  90. contents: [],
  91. is_show: false,
  92. relation_list: [], // 关联食堂列表
  93. node_top: 0,
  94. code: '', // 订单号,批次号,如果有
  95. type: 0
  96. }
  97. },
  98. computed: {
  99. selectName(){
  100. let arr = [];
  101. this.relation_list.map(item => {
  102. if(item.checked){
  103. arr.push(item.canteen_name);
  104. }
  105. });
  106. let str = '请选择...';
  107. if(arr.length > 0){
  108. str = arr.join(',');
  109. }
  110. return str;
  111. }
  112. },
  113. onLoad(options){
  114. this.code = options.code || '';
  115. this.type = options.type || 0;
  116. if(options.type == 1){
  117. // 编辑,不可更换食堂
  118. this.materialListByOrder();
  119. }else if(options.type == 2){
  120. // 复用订单号
  121. this.materialListByOrder();
  122. }else if(options.type == 3){
  123. // 复用批次号
  124. this.materialListByBatch();
  125. }else{
  126. // 单纯发起报价
  127. this.getMaterialList();
  128. }
  129. },
  130. onReady(){
  131. let that = this;
  132. let info = uni.createSelectorQuery().select(".relation");
  133.     info.boundingClientRect(function(data) {
  134. let num = app.globalData.customBarH;
  135. num += data.height;
  136. num += data.top;
  137. that.node_top = num;
  138.    }).exec()
  139. },
  140. onPageScroll(){
  141. if(this.is_show){
  142. this.is_show = false;
  143. }
  144. },
  145. methods: {
  146. // 获取物资列表
  147. getMaterialList(){
  148. this.$http(this.API.API_SUPPLIER_MATERIALLIST).then(res => {
  149. let list = res.data.spec || [];
  150. let contents = list.map(item => {
  151. return {
  152. name: item?.material?.m_name || '',
  153. material_id: item?.material?.id || 0,
  154. spec: item.name,
  155. spec_id: item.id,
  156. brand: item?.material?.brand || '',
  157. quality_level: item?.material?.quality_level || '',
  158. number: item?.material?.m_sn || '',
  159. purchase_limit: {edit: true, value: 1},
  160. tax_price: {edit: true, value: ''},
  161. non_tax_price: {edit: true, value: ''},
  162. operation: {button: true, key: 'delete', value: '删除'},
  163. unit: item?.material?.unit?.unit_name || '',
  164. category: item?.material?.category?.m_cate_name || ''
  165. }
  166. })
  167. this.contents = contents;
  168. this.getCanteenList();
  169. })
  170. },
  171. // 复用报价订单号 & 编辑共用
  172. materialListByOrder(){
  173. this.$http(this.API.API_SUPPLIER_QUOTATIONREUSEBYORDER, {
  174. q_sn: this.code
  175. }).then(res => {
  176. console.log("materialListByOrder", res);
  177. let list = res.data.order || [];
  178. let canteen = res.data.canteen || [];
  179. let contents = list.map(item => {
  180. let obj = {
  181. name: item?.material?.m_name || '',
  182. material_id: item?.material?.id || 0,
  183. spec: item.name,
  184. spec_id: item.id,
  185. brand: item?.material?.brand || '',
  186. quality_level: item?.material?.quality_level || '',
  187. number: item?.material?.m_sn || '',
  188. purchase_limit: {edit: true, value: item?.quotation?.purchase_limit || ''},
  189. tax_price: {edit: true, value: item?.quotation?.tax_price || ''},
  190. non_tax_price: {edit: true, value: item?.quotation?.non_tax_price || ''},
  191. quotation_id: item?.quotation?.id || 0,
  192. operation: {button: true, key: 'delete', value: '删除'},
  193. unit: item?.material?.unit?.unit_name || '',
  194. category: item?.material?.category?.m_cate_name || ''
  195. }
  196. if(item?.material?.state && item?.material?.state != '启用'){
  197. obj.disabled = true;
  198. }
  199. return obj;
  200. })
  201. this.contents = contents;
  202. this.getCanteenList(canteen);
  203. })
  204. },
  205. // 复用批次号
  206. materialListByBatch(){
  207. this.$http(this.API.API_SUPPLIER_QUOTATIONREUSEBYBATCH, {
  208. batch_sn: this.code
  209. }).then(res => {
  210. console.log("materialListByBatch", res);
  211. let list = res.data.order || [];
  212. let canteen = res.data.canteen || [];
  213. let contents = list.map(item => {
  214. return {
  215. name: item?.material?.m_name || '',
  216. material_id: item?.material?.id || 0,
  217. spec: item.name,
  218. spec_id: item.id,
  219. brand: item?.material?.brand || '',
  220. quality_level: item?.material?.quality_level || '',
  221. number: item?.material?.m_sn || '',
  222. purchase_limit: {edit: true, value: item?.quotation?.purchase_limit || ''},
  223. tax_price: {edit: true, value: item?.quotation?.tax_price || ''},
  224. non_tax_price: {edit: true, value: item?.quotation?.non_tax_price || ''}
  225. }
  226. })
  227. this.contents = contents;
  228. this.getCanteenList(canteen);
  229. })
  230. },
  231. // 关联食堂列表
  232. getCanteenList(canteen = []){
  233. this.$http(this.API.API_SUPPLIER_CANTEENLIST).then(res => {
  234. let list = res.data.list.map(item => {
  235. item.checked = false;
  236. canteen.map(ct => {
  237. if(ct == item.id){
  238. item.checked = true;
  239. }
  240. })
  241. return item;
  242. })
  243. this.relation_list = list;
  244. })
  245. },
  246. // 监听表格被输入
  247. onInputChange(event){
  248. this.contents[event.contentIndex][event.key].value = event.detailValue;
  249. },
  250. // table操作按钮被点击
  251. onButtonClick(event){
  252. if(event.content.key == 'delete'){
  253. let contentIndex = event.contentIndex;
  254. let name = event.lineData.name;
  255. let spec = event.lineData.spec;
  256. uni.showModal({
  257. title: '温馨提示',
  258. content: `确定删除 ${name}-${spec} 吗?`,
  259. confirmColor: '#1833F2',
  260. success: result => {
  261. if(result.confirm){
  262. this.contents.splice(contentIndex, 1);
  263. }
  264. }
  265. })
  266. }
  267. },
  268. // 切换显示关联食堂modal
  269. switchRelation(){
  270. if(this.type == 1) return this.$msg('编辑不可更换关联食堂哦');
  271. this.is_show = !this.is_show;
  272. },
  273. // 选择食堂
  274. selectItem(index){
  275. this.relation_list[index].checked = !this.relation_list[index].checked;
  276. },
  277. // 报价订单编辑时保存
  278. editMaterial(_t){
  279. // 物资列表
  280. let list = [];
  281. this.contents.map(item => {
  282. list.push({
  283. id: item.quotation_id,
  284. tax_price: item.tax_price.value,
  285. non_tax_price: item.non_tax_price.value,
  286. purchase_limit: Number(item.purchase_limit.value) || 1
  287. })
  288. });
  289. // 操作状态,是保存还是直接发起
  290. let state = ['待发起', '待审核'][_t];
  291. this.$http(this.API.API_SUPPLIER_QUOTATIONSAVE, {
  292. data: list,
  293. state: state,
  294. q_sn: this.code
  295. }).then(res => {
  296. this.$msg('操作成功').then(result => {
  297. this.$toBack();
  298. })
  299. })
  300. },
  301. // 保存
  302. save(_t){
  303. // 拦截是编辑的情况
  304. if(this.type == 1){
  305. this.editMaterial(_t);
  306. return;
  307. }
  308. // 物资列表
  309. let list = [];
  310. this.contents.map(item => {
  311. if(item.tax_price.value && item.non_tax_price.value){
  312. list.push({
  313. m_id: item.material_id,
  314. m_spec_id: item.spec_id,
  315. tax_price: item.tax_price.value,
  316. non_tax_price: item.non_tax_price.value,
  317. purchase_limit: Number(item.purchase_limit.value) || 1
  318. })
  319. }
  320. });
  321. // 关联食堂
  322. let canteen_ids = [];
  323. this.relation_list.map(item => {
  324. if(item.checked){
  325. canteen_ids.push(item.id);
  326. }
  327. })
  328. if(canteen_ids.length <= 0){
  329. return this.$msg('您未选择关联食堂哦')
  330. }
  331. if(list.length <= 0){
  332. return this.$msg('没有需要报价的物资')
  333. }
  334. // 操作状态,是保存还是直接发起
  335. let state = ['待发起', '待审核'][_t];
  336. this.$http(this.API.API_SUPPLIER_QUOTATIONAPPLY, {
  337. data: list,
  338. state: state,
  339. canteen_ids: canteen_ids
  340. }).then(res => {
  341. this.$msg(res.data).then(result => {
  342. this.$toBack();
  343. })
  344. })
  345. }
  346. }
  347. }
  348. </script>
  349. <style>
  350. page{
  351. overflow: hidden;
  352. }
  353. </style>
  354. <style lang="scss" scoped="scoped">
  355. .lf-m-t-5{
  356. margin-top: 5rpx;
  357. }
  358. .box{
  359. padding: 30rpx 32rpx;
  360. width: 100%;
  361. height: max-content;
  362. box-sizing: border-box;
  363. }
  364. .title{
  365. color: #222222;
  366. font-size: 28rpx;
  367. font-weight: bold;
  368. }
  369. .fixed-bottom{
  370. position: fixed;
  371. bottom: 0rpx;
  372. left: 0rpx;
  373. z-index: 99;
  374. width: 750rpx;
  375. height: 98rpx;
  376. display: flex;
  377. justify-content: center;
  378. align-items: center;
  379. border-top: 1rpx solid #E5E5E5;
  380. background-color: #fff;
  381. .btn{
  382. width: 320rpx;
  383. height: 82rpx;
  384. border-radius: 41rpx;
  385. margin: 0;
  386. padding: 0;
  387. font-size: 32rpx;
  388. display: flex;
  389. justify-content: center;
  390. align-items: center;
  391. }
  392. .btn1{
  393. border: 2rpx solid #555555;
  394. opacity: .5;
  395. }
  396. .btn2{
  397. background: #1833F2;
  398. color: #FFFFFF;
  399. margin-left: 50rpx;
  400. }
  401. }
  402. .relation{
  403. position: relative;
  404. border-bottom: 1rpx solid #E5E5E5;
  405. }
  406. .mask{
  407. position: fixed;
  408. background-color: rgba(0,0,0,0.4);
  409. width: 100%;
  410. // top: 149px;
  411. bottom: 0;
  412. left: 0;
  413. z-index: 100;
  414. .list{
  415. min-height: max-content;
  416. max-height: 500rpx;
  417. overflow: scroll;
  418. background-color: #FFFFFF;
  419. width: 100%;
  420. .item{
  421. height: 92rpx;
  422. padding: 0 32rpx;
  423. border-bottom: 1rpx solid #E5E5E5;
  424. color: #222222;
  425. font-size: 28rpx;
  426. }
  427. }
  428. }
  429. </style>