index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  4. <el-form-item label="分类索引" prop="moduleIndex">
  5. <el-input
  6. v-model="queryParams.moduleIndex"
  7. placeholder="2位"
  8. clearable
  9. @keyup.enter.native="handleQuery"
  10. />
  11. </el-form-item>
  12. <el-form-item label="子类路径" prop="category">
  13. <el-input
  14. v-model="queryParams.category"
  15. placeholder="正式为树结构选择"
  16. clearable
  17. @keyup.enter.native="handleQuery"
  18. />
  19. </el-form-item>
  20. <el-form-item label="属性列表" prop="attributes">
  21. <el-input
  22. v-model="queryParams.attributes"
  23. placeholder="请输入属性列表"
  24. clearable
  25. @keyup.enter.native="handleQuery"
  26. />
  27. </el-form-item>
  28. <el-form-item>
  29. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  30. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  31. </el-form-item>
  32. </el-form>
  33. <el-row :gutter="10" class="mb8">
  34. <el-col :span="1.5">
  35. <el-button
  36. type="primary"
  37. plain
  38. icon="el-icon-plus"
  39. size="mini"
  40. @click="handleAdd"
  41. v-hasPermi="['moduleConf:productConf:add']"
  42. >新增</el-button>
  43. </el-col>
  44. <el-col :span="1.5">
  45. <el-button
  46. type="success"
  47. plain
  48. icon="el-icon-edit"
  49. size="mini"
  50. :disabled="single"
  51. @click="handleUpdate"
  52. v-hasPermi="['moduleConf:productConf:edit']"
  53. >修改</el-button>
  54. </el-col>
  55. <el-col :span="1.5">
  56. <el-button
  57. type="danger"
  58. plain
  59. icon="el-icon-delete"
  60. size="mini"
  61. :disabled="multiple"
  62. @click="handleDelete"
  63. v-hasPermi="['moduleConf:productConf:remove']"
  64. >删除</el-button>
  65. </el-col>
  66. <el-col :span="1.5">
  67. <el-button
  68. type="warning"
  69. plain
  70. icon="el-icon-download"
  71. size="mini"
  72. @click="handleExport"
  73. v-hasPermi="['moduleConf:productConf:export']"
  74. >导出</el-button>
  75. </el-col>
  76. <el-col :span="1.5">
  77. <el-button
  78. type="info"
  79. plain
  80. icon="el-icon-upload2"
  81. size="mini"
  82. @click="handleImport"
  83. v-hasPermi="['moduleConf:productConf:import']"
  84. >导入</el-button>
  85. </el-col>
  86. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
  87. </el-row>
  88. <el-table :loading="loading" :data="sysList" @selection-change="handleSelectionChange">
  89. <el-table-column type="selection" width="55" align="center" />
  90. <!-- <el-table-column label="conf_id" :show-overflow-tooltip="true" v-if="columns[0].visible" prop="confId" />-->
  91. <el-table-column label="分类索引" align="center" :show-overflow-tooltip="true" v-if="columns[1].visible" prop="moduleIndex" />
  92. <el-table-column label="子类路径" align="center" :show-overflow-tooltip="true" v-if="columns[2].visible" prop="category" />
  93. <el-table-column label="属性列表" align="center" :show-overflow-tooltip="true" v-if="columns[3].visible" prop="attributes" />
  94. <el-table-column label="版本号" align="center" :show-overflow-tooltip="true" v-if="columns[4].visible" prop="version" />
  95. <el-table-column label="删除标记" align="center" :show-overflow-tooltip="true" v-if="columns[5].visible" prop="deleteFlag">
  96. <template slot-scope="scope">
  97. <span v-if="scope.row.deleteFlag === 0">未删除</span>
  98. <span v-else-if="scope.row.deleteFlag === 1">已删除</span>
  99. <span v-else>-</span>
  100. </template>
  101. </el-table-column>
  102. <el-table-column label="状态" align="center" :show-overflow-tooltip="true" v-if="columns[6].visible" prop="status">
  103. <template slot-scope="scope">
  104. <span v-if="scope.row.status === 0">禁用</span>
  105. <span v-else-if="scope.row.status === 1">启用</span>
  106. <span v-else>-</span>
  107. </template>
  108. </el-table-column>
  109. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  110. <template slot-scope="scope">
  111. <el-button
  112. size="mini"
  113. type="text"
  114. icon="el-icon-edit"
  115. @click="handleUpdate(scope.row)"
  116. v-hasPermi="['moduleConf:productConf:edit']"
  117. >修改</el-button>
  118. <el-button
  119. size="mini"
  120. type="text"
  121. icon="el-icon-delete"
  122. @click="handleDelete(scope.row)"
  123. v-hasPermi="['moduleConf:productConf:remove']"
  124. >删除</el-button>
  125. </template>
  126. </el-table-column>
  127. </el-table>
  128. <pagination
  129. v-show="total>0"
  130. :total="total"
  131. :page.sync="queryParams.pageNum"
  132. :limit.sync="queryParams.pageSize"
  133. @pagination="getList"
  134. />
  135. <!-- 添加或修改单品配置表对话框 -->
  136. <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
  137. <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  138. <!-- <el-form-item label="conf_id" prop="confId">-->
  139. <!-- <el-input v-model="form.confId" placeholder="请输入conf_id" />-->
  140. <!-- </el-form-item>-->
  141. <el-form-item label="分类索引" prop="moduleIndex">
  142. <el-input v-model="form.moduleIndex" placeholder="请输入分类索引" />
  143. </el-form-item>
  144. <el-form-item label="子类路径" prop="category">
  145. <el-input v-model="form.category" placeholder="请输入子类路径" />
  146. </el-form-item>
  147. <el-form-item label="版本号" prop="version">
  148. <el-input-number v-model="form.version" :min="0" placeholder="请输入版本号" style="width: 100%" />
  149. </el-form-item>
  150. <el-form-item label="删除标记" prop="deleteFlag">
  151. <el-radio-group v-model="form.deleteFlag">
  152. <el-radio :label="0">未删除</el-radio>
  153. <el-radio :label="1">已删除</el-radio>
  154. </el-radio-group>
  155. </el-form-item>
  156. <el-form-item label="状态" prop="status">
  157. <el-radio-group v-model="form.status">
  158. <el-radio :label="0">禁用</el-radio>
  159. <el-radio :label="1">启用</el-radio>
  160. </el-radio-group>
  161. </el-form-item>
  162. <el-form-item label="属性设置" prop="attributes">
  163. <div style="width: 100%;">
  164. <el-table :data="attrList" border style="width: 100%" size="small" max-height="400">
  165. <el-table-column label="属性名" width="150">
  166. <template slot-scope="scope">
  167. <el-input v-model="scope.row.attrName" placeholder="请输入属性名" size="small" />
  168. </template>
  169. </el-table-column>
  170. <el-table-column label="属性标识" width="150">
  171. <template slot-scope="scope">
  172. <el-input v-model="scope.row.attr" placeholder="请输入属性标识" size="small" />
  173. </template>
  174. </el-table-column>
  175. <el-table-column label="类型" width="280">
  176. <template slot-scope="scope">
  177. <el-radio-group v-model="scope.row.type" size="small">
  178. <el-radio-button label="int">整数</el-radio-button>
  179. <el-radio-button label="double">小数</el-radio-button>
  180. <el-radio-button label="string">字符串</el-radio-button>
  181. <el-radio-button label="datatime">日期</el-radio-button>
  182. <el-radio-button label="decimal">金额</el-radio-button>
  183. </el-radio-group>
  184. </template>
  185. </el-table-column>
  186. <el-table-column label="描述" min-width="200">
  187. <template slot-scope="scope">
  188. <el-input v-model="scope.row.description" placeholder="请输入描述" size="small" />
  189. </template>
  190. </el-table-column>
  191. <el-table-column label="操作" width="100" align="center" fixed="right">
  192. <template slot-scope="scope">
  193. <el-button
  194. size="mini"
  195. type="danger"
  196. icon="el-icon-delete"
  197. @click="removeAttrRow(scope.$index)"
  198. >删除</el-button>
  199. </template>
  200. </el-table-column>
  201. </el-table>
  202. <div style="margin-top: 10px;">
  203. <el-button type="primary" size="small" icon="el-icon-plus" @click="addAttrRow">添加属性</el-button>
  204. </div>
  205. </div>
  206. </el-form-item>
  207. </el-form>
  208. <div slot="footer" class="dialog-footer">
  209. <el-button type="primary" @click="submitForm">确 定</el-button>
  210. <el-button @click="cancel">取 消</el-button>
  211. </div>
  212. </el-dialog>
  213. <!-- 导入对话框 -->
  214. <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
  215. <el-upload
  216. ref="upload"
  217. :limit="1"
  218. accept=".xlsx, .xls"
  219. :headers="upload.headers"
  220. :action="upload.url + '?updateSupport=' + upload.updateSupport"
  221. :disabled="upload.isUploading"
  222. :on-progress="handleFileUploadProgress"
  223. :on-success="handleFileSuccess"
  224. :auto-upload="false"
  225. drag
  226. >
  227. <i class="el-icon-upload"></i>
  228. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  229. <div class="el-upload__tip text-center" slot="tip">
  230. <div class="el-upload__tip" slot="tip">
  231. <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的单品配置表数据
  232. </div>
  233. <span>仅允许导入xls、xlsx格式文件。</span>
  234. <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
  235. </div>
  236. </el-upload>
  237. <div slot="footer" class="dialog-footer">
  238. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  239. <el-button @click="upload.open = false">取 消</el-button>
  240. </div>
  241. </el-dialog>
  242. </div>
  243. </template>
  244. <script>
  245. import { listProductConf, getProductConf, delProductConf, addProductConf, updateProductConf } from "@/api/system/moduleConf/productConf";
  246. import { getToken } from "@/utils/auth";
  247. export default {
  248. name: "ProductConf",
  249. data() {
  250. return {
  251. // 遮罩层
  252. loading: true,
  253. // 选中数组
  254. ids: [],
  255. // 非单个禁用
  256. single: true,
  257. // 非多个禁用
  258. multiple: true,
  259. // 显示搜索条件
  260. showSearch: true,
  261. // 总条数
  262. total: 0,
  263. // 单品配置表表格数据
  264. sysList: [],
  265. // 表格列信息
  266. columns: [
  267. { key: 0, label: 'conf_id', visible: false },
  268. { key: 1, label: '分类索引', visible: true },
  269. { key: 2, label: '子类路径', visible: true },
  270. { key: 3, label: '属性列表', visible: true },
  271. { key: 4, label: '版本号', visible: true },
  272. { key: 5, label: '删除标记', visible: true },
  273. { key: 6, label: '状态', visible: true }
  274. ],
  275. // 弹出层标题
  276. title: "",
  277. // 是否显示弹出层
  278. open: false,
  279. // 查询参数
  280. queryParams: {
  281. pageNum: 1,
  282. pageSize: 10,
  283. // confId: null,
  284. moduleIndex: null,
  285. category: null,
  286. attributes: null
  287. },
  288. // 表单参数
  289. form: {},
  290. // 属性列表数据
  291. attrList: [],
  292. // 导入参数
  293. upload: {
  294. // 是否显示弹出层(导入)
  295. open: false,
  296. // 弹出层标题(导入)
  297. title: "",
  298. // 是否禁用上传
  299. isUploading: false,
  300. // 是否更新已经存在的单品配置表数据
  301. updateSupport: 0,
  302. // 设置上传的请求头部
  303. headers: { Authorization: "Bearer " + getToken() },
  304. // 上传的地址
  305. url: process.env.VUE_APP_BASE_API + "/test/sys/importData"
  306. },
  307. // 表单校验
  308. rules: {
  309. // confId: [
  310. // { required: true, message: "conf_id不能为空", trigger: "blur" }
  311. // ],
  312. category: [
  313. { required: true, message: "子类路径不能为空", trigger: "blur" }
  314. ],
  315. attributes: [
  316. { required: false, message: "请设置属性", trigger: "change" }
  317. ]
  318. }
  319. };
  320. },
  321. created() {
  322. this.getList();
  323. },
  324. methods: {
  325. /** 查询单品配置表列表 */
  326. getList() {
  327. this.loading = true;
  328. listProductConf(this.queryParams).then(response => {
  329. this.sysList = response.rows;
  330. this.total = response.total;
  331. this.loading = false;
  332. });
  333. },
  334. // 取消按钮
  335. cancel() {
  336. this.open = false;
  337. this.reset();
  338. },
  339. // 表单重置
  340. reset() {
  341. this.form = {
  342. moduleIndex: null,
  343. category: null,
  344. attributes: null,
  345. version: null,
  346. deleteFlag: 0,
  347. status: 1
  348. };
  349. this.attrList = [];
  350. this.resetForm("form");
  351. },
  352. /** 搜索按钮操作 */
  353. handleQuery() {
  354. this.queryParams.pageNum = 1;
  355. this.getList();
  356. },
  357. /** 重置按钮操作 */
  358. resetQuery() {
  359. this.resetForm("queryForm");
  360. this.handleQuery();
  361. },
  362. // 多选框选中数据
  363. handleSelectionChange(selection) {
  364. this.ids = selection.map(item => item.confId)
  365. this.single = selection.length!==1
  366. this.multiple = !selection.length
  367. },
  368. /** 新增按钮操作 */
  369. handleAdd() {
  370. this.reset();
  371. // 新增时添加一个默认空行
  372. this.addAttrRow();
  373. this.open = true;
  374. this.title = "添加单品配置表";
  375. },
  376. /** 修改按钮操作 */
  377. handleUpdate(row) {
  378. this.reset();
  379. const confId = row.confId || this.ids
  380. getProductConf(confId).then(response => {
  381. this.form = response.data;
  382. // 解析attributes JSON字符串为attrList
  383. if (this.form.attributes) {
  384. try {
  385. this.attrList = JSON.parse(this.form.attributes);
  386. // 确保是数组格式
  387. if (!Array.isArray(this.attrList)) {
  388. this.attrList = [];
  389. }
  390. } catch (e) {
  391. console.error("解析attributes失败:", e);
  392. this.attrList = [];
  393. }
  394. } else {
  395. this.attrList = [];
  396. }
  397. this.open = true;
  398. this.title = "修改单品配置表";
  399. });
  400. },
  401. /** 提交按钮 */
  402. submitForm() {
  403. this.$refs["form"].validate(valid => {
  404. if (valid) {
  405. const submitData = this.buildSubmitData();
  406. if (submitData.confId != null) {
  407. updateProductConf(submitData).then(response => {
  408. this.$modal.msgSuccess("修改成功");
  409. this.open = false;
  410. this.getList();
  411. });
  412. } else {
  413. addProductConf(submitData).then(response => {
  414. this.$modal.msgSuccess("新增成功");
  415. this.open = false;
  416. this.getList();
  417. });
  418. }
  419. }
  420. });
  421. },
  422. /** 删除按钮操作 */
  423. handleDelete(row) {
  424. const sysIds = row.confId || this.ids;
  425. this.$modal.confirm('是否确认删除单品配置表编号为"' + sysIds + '"的数据项?').then(function() {
  426. return delProductConf(sysIds);
  427. }).then(() => {
  428. this.getList();
  429. this.$modal.msgSuccess("删除成功");
  430. }).catch(() => {});
  431. },
  432. /** 导出按钮操作 */
  433. handleExport() {
  434. this.download('test/sys/export', {
  435. ...this.queryParams
  436. }, `sys_${new Date().getTime()}.xlsx`)
  437. },
  438. /** 导入按钮操作 */
  439. handleImport() {
  440. this.upload.title = "单品配置表导入";
  441. this.upload.open = true;
  442. },
  443. /** 下载模板操作 */
  444. importTemplate() {
  445. this.download(
  446. "test/sys/importTemplate",
  447. {},
  448. "sys_template_" + new Date().getTime() + ".xlsx"
  449. );
  450. },
  451. // 文件上传中处理
  452. handleFileUploadProgress(event, file, fileList) {
  453. this.upload.isUploading = true;
  454. },
  455. // 文件上传成功处理
  456. handleFileSuccess(response, file, fileList) {
  457. this.upload.open = false;
  458. this.upload.isUploading = false;
  459. this.$refs.upload.clearFiles();
  460. this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
  461. this.$modal.closeLoading()
  462. this.getList();
  463. },
  464. buildSubmitData() {
  465. // 只保留实体类中定义的字段,过滤掉其他字段
  466. const data = {};
  467. // 只添加存在的字段,避免提交 undefined 或空字符串
  468. if (this.form.moduleIndex !== undefined && this.form.moduleIndex !== null && this.form.moduleIndex !== "") {
  469. data.moduleIndex = this.form.moduleIndex;
  470. }
  471. if (this.form.category !== undefined && this.form.category !== null && this.form.category !== "") {
  472. data.category = this.form.category;
  473. }
  474. if (this.form.version !== undefined && this.form.version !== null) {
  475. data.version = this.form.version;
  476. }
  477. if (this.form.deleteFlag !== undefined && this.form.deleteFlag !== null) {
  478. data.deleteFlag = this.form.deleteFlag;
  479. }
  480. if (this.form.status !== undefined && this.form.status !== null) {
  481. data.status = this.form.status;
  482. }
  483. // 将attrList序列化为JSON字符串
  484. if (this.attrList && this.attrList.length > 0) {
  485. data.attributes = JSON.stringify(this.attrList);
  486. } else {
  487. data.attributes = null;
  488. }
  489. // 如果是修改操作,需要包含 confId
  490. if (this.form.confId !== null && this.form.confId !== undefined && this.form.confId !== "") {
  491. data.confId = this.form.confId;
  492. }
  493. return data;
  494. },
  495. // 添加属性行
  496. addAttrRow() {
  497. this.attrList.push({
  498. attrName: "",
  499. attr: "",
  500. type: "字符串",
  501. description: ""
  502. });
  503. },
  504. // 删除属性行
  505. removeAttrRow(index) {
  506. this.attrList.splice(index, 1);
  507. },
  508. // 提交上传文件
  509. submitFileForm() {
  510. this.$modal.loading("导入中请稍后")
  511. this.$refs.upload.submit();
  512. }
  513. }
  514. };
  515. </script>