edit.blade.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. @extends('layouts.base')
  2. @section('content')
  3. @section('title', trans('配置编辑'))
  4. @include('public.admin.box-item')
  5. <style scoped>
  6. .fixed {
  7. width: calc(100% - 250px);
  8. padding: 7px;
  9. padding-top: 10px;
  10. position: fixed;
  11. bottom: 0px;
  12. z-index: 1999;
  13. box-sizing: border-box;
  14. box-shadow: 0px -1px 10px rgb(0 0 0 / 10%);
  15. margin-left: -14px;
  16. background-color: #fff;
  17. border-radius: 20px 20px 0 0;
  18. }
  19. .fixed_box {
  20. height: 60px;
  21. display: flex;
  22. justify-content: center;
  23. align-items: center;
  24. }
  25. .addItem {
  26. width: 100px;
  27. height: 100px;
  28. border: 1px dashed rgb(217, 220, 223);
  29. display: flex;
  30. align-items: center;
  31. justify-content: center;
  32. text-align: center;
  33. line-height: 1;
  34. }
  35. .el-icon-plus {
  36. font-size: 30px;
  37. margin: -10px 0 10px;
  38. }
  39. .el-dialog {
  40. display: flex;
  41. flex-direction: column;
  42. margin: 0 !important;
  43. position: absolute;
  44. top: 50%;
  45. left: 50%;
  46. transform: translate(-50%, -50%);
  47. border-radius: 20px;
  48. padding-bottom: 20px;
  49. width: 50vw;
  50. height: 700px;
  51. overflow-y: auto;
  52. }
  53. .el-dialog__title {
  54. height: 74px;
  55. }
  56. .el-dialog__body {
  57. height: 504px;
  58. padding: 0 20px;
  59. }
  60. .commodity-show .el-dialog__body {
  61. height: 520px;
  62. }
  63. .commodity-show .el-dialog__footer {
  64. height: 122px;
  65. }
  66. .commodity-show .table-list {
  67. height: 440px;
  68. overflow-y: auto;
  69. margin-top: 20px;
  70. }
  71. .commodity-show .search-box {
  72. display: flex;
  73. height: 40px;
  74. /* line-height: 40px; */
  75. align-items: center;
  76. }
  77. .commodity-show .search-item {
  78. width: 120px;
  79. margin-right: 10px;
  80. }
  81. .search-item1 {
  82. width: 200px;
  83. margin-right: 10px;
  84. }
  85. .selectNo {}
  86. .select-search {
  87. display: flex;
  88. margin: 20px 0;
  89. }
  90. .select-search .el-input {
  91. width: 200px;
  92. margin-right: 20px;
  93. }
  94. .goods-info {
  95. height: 32px;
  96. text-overflow: -o-ellipsis-lastline;
  97. overflow: hidden;
  98. text-overflow: ellipsis;
  99. display: -webkit-box;
  100. -webkit-line-clamp: 2;
  101. line-clamp: 2;
  102. -webkit-box-orient: vertical;
  103. }
  104. .good-list {
  105. margin: 0 0 10px 10px;
  106. width: 100px;
  107. position: relative;
  108. }
  109. .del-icon {
  110. width: 20px;
  111. height: 20px;
  112. background-color: rgb(221, 226, 238);
  113. display: flex;
  114. align-items: center;
  115. justify-content: center;
  116. position: absolute;
  117. right: -10px;
  118. top: -10px;
  119. border-radius: 50%;
  120. }
  121. .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
  122. color: #29BA9C;
  123. }
  124. [v-cloak]{display: none;}
  125. .code-list{display: flex;height: 100%;}
  126. .code-list .el-tree-box{border-right: 1px solid rgba(238,238,238,1);width: 260px;margin-right: 20px;height:100%;overflow-y: auto;}
  127. .code-list .el-tree-box .el-tree{width: 250px;overflow-x: auto;margin-right: 10px;}
  128. .is-leaf .el-tree-node_expand-icon {display:none !important;}
  129. .dialog-footer{text-align: center;padding-top: 20px;}
  130. .code-table-box{flex: 1;height: 100%;padding: 0 10px;overflow-y: auto;}
  131. .category-tree-box{margin-top: 20px;max-height: 440px;overflow-y: auto;}
  132. </style>
  133. <div class="all">
  134. <div id="app" v-cloak>
  135. <box-item text="配置开票商品">
  136. <el-form ref="form" :model="form" label-width="260px">
  137. <el-form-item label="税收分类编码" :rules="rules('税收分类编码')" prop="code">
  138. <el-tag v-if="form.code" closable @close="delTag">[[form.code]][[form.name]]</el-tag>
  139. <el-button @click="clickCode">税收分类编码</el-button>
  140. </el-form-item>
  141. <el-form-item label="开票商品" :rules="goods_rules('税收分类编码')" prop="has_many_goods" class="is-required">
  142. <div style="display:flex;flex-wrap: wrap;">
  143. <div class="addItem" @click="openCommodity">
  144. <div>
  145. <div class="el-icon-plus"></div>
  146. <div>选择商品</div>
  147. </div>
  148. </div>
  149. <div class="good-list" v-for="(item,i) in form.has_many_goods" :key="i">
  150. <div class="del-icon" @click="deleteGoogs(i,form.has_many_goods)">X</div>
  151. <img :src="item.thumb" alt="" srcset="" style="width:100px;height:100px;">
  152. <div style="line-height:20px;">[[item.title]][["[id:"+item.id+"]"]]</div>
  153. </div>
  154. </div>
  155. <div>
  156. <el-tag closable v-for="(item,i) in form.has_many_category" @close="delTag('分类',i)" :key="i">[["分类名称:"+(item.name||item.category_name)]]</el-tag>
  157. </div>
  158. </el-form-item>
  159. <el-form-item label="免税类型" :rules="rules('免税类型')" prop="tax_type">
  160. <el-select v-model="form.tax_type" placeholder="请选择" clearable>
  161. <el-option v-for="(item,i) in exemptionType" :label="(item>=0?(item+'%'):item)" :value="item" :key="i"> </el-option>
  162. </el-select>
  163. </el-form-item>
  164. <el-form-item label="税率" :rules="rules('税率')" prop="tax_rate">
  165. <el-select v-model="form.tax_rate" placeholder="请选择" clearable>
  166. <el-option v-for="(item,i) in taxRate" :key="i" :label="item+'%'" :value="item"> </el-option>
  167. </el-select>
  168. </el-form-item>
  169. </el-form>
  170. </box-item>
  171. <div class="fixed">
  172. <div class="fixed_box">
  173. <el-button type="primary" @click="Submit('ruleForm')">提交</el-button>
  174. </div>
  175. </div>
  176. <el-dialog title="选择税收分类编码" :visible.sync="codeShow" width="800px" :before-close="isCodeShow">
  177. <div class="select-search">
  178. <el-input v-model="code_info" style="width: 200px;margin-right: 20px;" placeholder="请输入税收编码或关键字" @keyup.enter.native="searchNode(code_info)"></el-input>
  179. <el-button type="primary" icon="el-icon-search" @click="searchNode(code_info)">搜 索</el-button>
  180. </div>
  181. <div class="code-list">
  182. <div class="el-tree-box">
  183. <el-tree :props="{label: 'mc',children: 'children'}" :highlight-current="true" @node-click="clickNode" ref="tree" node-key="bm" :data="codeListData" :filter-node-method="filterNode"></el-tree>
  184. </div>
  185. <div class="code-table-box">
  186. <el-table :data="codeList" style="width: 100%;" v-loading="codeLoading">
  187. <el-table-column prop="mc" label="分类简称" align="center"></el-table-column>
  188. <el-table-column prop="bm" label="税收分类编码" align="center"></el-table-column>
  189. <el-table-column label="操作" align="center" width="60">
  190. <template slot-scope="scope">
  191. <el-button @click="choiceCode(scope.row)" type="text" size="small">选择</el-button>
  192. </template>
  193. </el-table-column>
  194. </el-table>
  195. </div>
  196. </div>
  197. </el-dialog>
  198. <div class="commodity-show">
  199. <el-dialog :title="type==0?'选择商品':'选择分类'" :visible.sync="commodityShow">
  200. <div class="search-box">
  201. <el-select v-model="type" placeholder="请选择" class="search-item" @change="changeType">
  202. <el-option label="商品" value="0"></el-option>
  203. <el-option label="分类" value="1"></el-option>
  204. </el-select>
  205. <template v-if="type==0">
  206. <el-input v-model="goods_info" placeholder="请输入商品信息" class="search-item1"></el-input>
  207. <el-select v-model="isCode" placeholder="是否已关联税收分类编码" class="search-item1" clearable>
  208. <el-option label="是" value="1"></el-option>
  209. <el-option label="否" value="0"></el-option>
  210. </el-select>
  211. </template>
  212. <template v-if="type!=0">
  213. <el-input v-model="categoryValue" placeholder="请输入分类名称" class="search-item1"></el-input>
  214. </template>
  215. <el-button type="primary" icon="el-icon-search" @click="searchVal">搜 索</el-button>
  216. </div>
  217. <div class="table-list" v-show="type=='0'">
  218. <el-table :data="goodsList" :row-key="getRowKey" ref="goodsTable">
  219. <!-- <el-table-column type="selection" width="55" :reserve-selection="true"></el-table-column> -->
  220. <el-table-column label="商品名称" align="left">
  221. <template slot-scope="scope">
  222. <div style="display:flex;">
  223. <div style="width:50px;height:50px;">
  224. <img :src="scope.row.thumb" width="100%" height="100%">
  225. </div>
  226. <div class="" style="color:#333;font-size:14px;line-height:16px;margin-left:10px;flex:1;">
  227. <div class="goods-info">[["[id"+scope.row.id+"]" + scope.row.title]]</div>
  228. <div class="goods-price">[["¥"+scope.row.price]]</div>
  229. </div>
  230. </div>
  231. </template>
  232. </el-table-column>
  233. <el-table-column label="已关联税收分类编码" align="center">
  234. <template slot-scope="scope">
  235. <div v-if="scope.row.code">[[scope.row.code]]</div>
  236. <div v-else>
  237. [[scope.row.has_one_invoice_goods&&scope.row.has_one_invoice_goods?scope.row.has_one_invoice_goods.code:"暂无"]]
  238. </div>
  239. </template>
  240. </el-table-column>
  241. <el-table-column width="120">
  242. <template slot-scope="scope">
  243. <el-button type="text" @click="handleSelectionChange(scope.row)">[[getChangeGoods(scope.row.id)?"已":""]]选择</el-button>
  244. </template>
  245. </el-table-column>
  246. </el-table>
  247. </div>
  248. <div class="category-tree-box" v-show="type!='0'">
  249. <el-tree :props="categoryProps()" :load="loadCategory" lazy show-checkbox :data="categoryList" @check-change="changeCategoryList" :default-checked-keys="tree_checked" node-key="id"></el-tree>
  250. </div>
  251. <div slot="footer" class="dialog-footer">
  252. <el-pagination @current-change="handleCurrentChange" :current-page.sync="currentPage" :page-size="goodsPageSize" layout="prev, pager, next, jumper" :total="goodsTotal" style="margin: 10px 0;">
  253. </el-pagination>
  254. <!-- <div>
  255. <el-button @click="commodityShow = false">取 消</el-button>
  256. <el-button type="primary" @click="commodityShow = false">确 定</el-button>
  257. </div> -->
  258. </div>
  259. </el-dialog>
  260. </div>
  261. </div>
  262. </div>
  263. <script>
  264. let pramsId = "{{ request()-> id }}";
  265. const vm = new Vue({
  266. el: "#app",
  267. delimiters: ['[[', ']]'],
  268. data() {
  269. return {
  270. isCode: "",
  271. goods_info: "",
  272. code_info: "",
  273. isFfirst:true,
  274. tree_checked:[],//默认选择的分类
  275. goods_checked:[],//选择商品的id
  276. categoryValue:"",
  277. exemptionType: ["出口免税和其他免税优惠政策","不征增值税","普通零税率","0","1","3"],
  278. taxRate: [0, 1, 3 ],
  279. categoryList: [],
  280. isFirst: false,
  281. isGetCodeData: true,
  282. codeList: [],
  283. codeLoading: false,
  284. currentPage: 1,
  285. type: "0",
  286. value: "",
  287. commodityShow: false,
  288. goodsList: [],
  289. goodsTotal: 0,
  290. goodsPageSize: 0,
  291. last_page: null,
  292. selectdata: [],
  293. codeShow: false,
  294. tableData: [],
  295. form: {
  296. tax_type: "",
  297. tax_rate: "",
  298. name: "",
  299. code: "",
  300. has_many_goods: [],
  301. has_many_category: []
  302. },
  303. codeListData:[],
  304. }
  305. },
  306. created() {
  307. if (pramsId) this.editData(null);
  308. },
  309. methods: {
  310. categoryProps(){
  311. return {label: 'name',children: 'children',isLeaf:(data,node)=>{
  312. if (data.has_many_children && data.has_many_children.length<=0) {
  313. return true
  314. }
  315. }}
  316. },
  317. rules: (msg) => {
  318. return { required: true,message: '请选择' + msg,trigger: 'blur'}
  319. },
  320. goods_rules(){
  321. let rules = (rule, value, callback)=>{
  322. if ((value&&value.length>0) || (this.form.has_many_category&&this.form.has_many_category.length>0)) callback()
  323. else callback(new Error('请选择开票商品'))
  324. }
  325. return { validator: rules, trigger: 'blur'}
  326. },
  327. clickCode(){
  328. this.codeShow = true;
  329. if (this.codeListData.length<=0) {
  330. this.getCodeListData()
  331. }
  332. },
  333. changeCategoryList(data) {
  334. let has_many_category = this.form.has_many_category;
  335. let i = has_many_category.indexOf(data);
  336. if (i == -1) {
  337. has_many_category.push(data);
  338. this.tree_checked.push(data.id);
  339. }else {
  340. has_many_category.splice(i, 1);
  341. this.tree_checked.splice(i,1);
  342. }
  343. this.form.has_many_category = has_many_category;
  344. },
  345. getCodeListData(node){
  346. this.codeLoading = true;
  347. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.get-code')!!}").then(({data:{result,msg,data}})=>{
  348. if(result==1){
  349. this.codeListData = data;
  350. this.$nextTick(()=>this.$refs.tree.filter(this.code_info))
  351. this.codeLoading = false;
  352. }else this.$message.error(msg)
  353. })
  354. },
  355. clickNode(data,node){
  356. this.filterCode(data.children);
  357. },
  358. searchNode(value){
  359. this.codeLoading = true;
  360. this.codeList = [];
  361. this.cahngeNode = false;
  362. this.$refs.tree.filter(value);
  363. this.$nextTick(()=>{
  364. if (this.code_info == "") {
  365. this.codeLoading = false;
  366. return
  367. }
  368. this.filterCode(this.cahngeNode.children,value);
  369. this.$refs.tree.setCurrentKey(this.cahngeNode.bm);
  370. this.codeLoading = false;
  371. })
  372. },
  373. filterNode(value, data, node){
  374. if (value=="" || this.code_info=="") return data.children.length>0;
  375. let bool = false,childrenbool = false;
  376. if ((data.bm.indexOf(value)!== -1) || (data.mc.indexOf(value)!== -1) || (data.spbmjc.indexOf(value)!== -1)) {
  377. if (data.children.length<=0) {
  378. this.cahngeNode = node.parent.data || {}
  379. }else{
  380. this.cahngeNode = data;
  381. }
  382. if(data.children.length>0) bool = true;
  383. if (!this.cahngeNode) this.cahngeNode = data.children.length<=0?(node.parent.data || {}) : data;
  384. }
  385. for (let i = 0; i < data.children.length; i++) {
  386. const item = data.children[i];
  387. if((item.bm.indexOf(value)!== -1) || (item.mc.indexOf(value)!== -1) || (item.spbmjc.indexOf(value)!== -1)){
  388. childrenbool = true;
  389. break;
  390. }
  391. }
  392. return bool || childrenbool;
  393. },
  394. filterCode(data = [],value){
  395. this.codeList = data.filter(item=>{
  396. if(item.children.length>0){
  397. list.push(item);
  398. return false;
  399. }else return true;
  400. return item.children.length<=0
  401. })
  402. },
  403. choiceCode({zzssl,bm,mc}) {
  404. zzssl = zzssl.split("%")[0];
  405. this.form.tax_rate = zzssl;
  406. this.exemptionType = ["出口免税和其他免税优惠政策","不征增值税","普通零税率","0","1","3",zzssl+""],
  407. this.taxRate = [0, 1, 3 ,zzssl],
  408. this.form.code = bm;
  409. this.form.name = mc;
  410. this.codeShow = false;
  411. },
  412. searchVal() {
  413. this.goodsTotal = 0;
  414. this.currentPage = 1;
  415. if(this.type==0) this.getGoodsList(1, this.isCode, this.goods_info);
  416. else this.getCategoryList(1,this.categoryValue)
  417. },
  418. changeType(type) {
  419. this.goodsTotal = 0;
  420. this.currentPage = 1;
  421. if (type == 0) this.getGoodsList(1)
  422. else this.getCategoryList(1)
  423. },
  424. getGoodsList(page = "1", relation, name) {
  425. let json = {code: this.form.code,page};
  426. if (relation) json.relation = relation;
  427. if (name) json.name = name;
  428. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.get-goods')!!}", json).then(({data: {result,msg = "",data} }) => {
  429. if (result == 1 && data) {
  430. this.tableInfo(data, "goodsList");
  431. let list = this.form.has_many_goods || [];
  432. }else this.$message.error(msg);
  433. })
  434. },
  435. tableInfo(data, key) {
  436. this.last_page = data.last_page;
  437. this.goodsPageSize = data.per_page;
  438. this.goodsTotal = data.total;
  439. if (key) this[key] = data.data;
  440. },
  441. openCommodity(i) {
  442. this.commodityShow = true;
  443. if(this.type==0) {
  444. this.getGoodsList(1);
  445. }
  446. else this.getCategoryList(1);
  447. },
  448. deleteGoogs(i,goods){
  449. goods.splice(i,1);
  450. },
  451. loadCategory(node, resolve) {
  452. let json = node.data && node.data.id ? {category_id: node.data.id} : {};
  453. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.get-category')!!}", json).then(({data: {result,msg = "错误",data}}) => {
  454. if (result == 1) {
  455. if (!this.isFirst) {
  456. this.tableInfo(data);
  457. this.isFirst = true;
  458. }
  459. return resolve(data.data);
  460. } else {
  461. this.$message.error(msg)
  462. return []
  463. }
  464. })
  465. },
  466. editData(formData) {
  467. let json = {id: pramsId}
  468. if (formData) json.data = formData;
  469. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.change')!!}", json).then(({data: {result,msg,data}}) => {
  470. if (result == 1) {
  471. if (!formData) {
  472. let category = data.has_many_category;
  473. let dataForm = {
  474. tax_rate: data.tax_rate,
  475. tax_type: data.tax_type,
  476. code: data.code,
  477. has_many_goods: data.has_many_goods,
  478. has_many_category: category,
  479. name: data.name || ""
  480. }
  481. this.tree_checked = [];
  482. category.forEach(item=>{
  483. this.tree_checked.push(item.id);
  484. })
  485. this.form = dataForm;
  486. } else {
  487. this.$message.success("保存成功");
  488. history.go(-1);
  489. }
  490. } else this.$message.error(msg)
  491. })
  492. },
  493. Submit() {
  494. this.$refs.form.validate((valid) => {
  495. if (valid) {
  496. if (pramsId) this.editData(this.form);
  497. else {
  498. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.store')!!}", {data: this.form}).then(({data: {result,msg}}) => {
  499. if (result==1) {
  500. this.$message.success(msg)
  501. history.go(-1);
  502. }else this.$message.error(msg)
  503. })
  504. }
  505. } else {
  506. this.$message.error("必填项不能为空")
  507. }
  508. })
  509. },
  510. isCodeShow() {
  511. this.codeShow = false;
  512. },
  513. delTag(name, i) {
  514. if (name == "分类") {
  515. this.form.has_many_category.splice(i, 1);
  516. this.tree_checked.splice(i,1)
  517. }
  518. else {
  519. this.form.code = "";
  520. this.form.name = "";
  521. }
  522. },
  523. getRowKey(row) {
  524. return row.id
  525. },
  526. getChangeGoods(id){
  527. let goods = this.form.has_many_goods;
  528. for (let index = 0; index < goods.length; index++) {
  529. const item = goods[index];
  530. if (item.id == id) {
  531. return {i:index};
  532. }
  533. }
  534. return false;
  535. },
  536. handleSelectionChange(row) {
  537. let bool = this.getChangeGoods(row.id,"该商品已选择");
  538. if (bool===false) {
  539. this.form.has_many_goods.push(row)
  540. }else{
  541. this.form.has_many_goods.splice(bool.i,1)
  542. }
  543. },
  544. getCategoryList(page,name){
  545. let json = {page};
  546. if(name) json.name = name;
  547. this.$http.post("{!!yzWebFullUrl('plugin.invoice.admin.invoicing-goods.get-category')!!}", json).then(({data: { result, msg, data }}) => {
  548. if (result == 1) {
  549. this.tableInfo(data, "categoryList");
  550. }else this.$message.error(msg)
  551. })
  552. },
  553. handleCurrentChange(page) {
  554. if (this.type == 0) this.getGoodsList(page)
  555. else this.getCategoryList(page)
  556. },
  557. }
  558. })
  559. </script>
  560. @endsection('content')