dataInfo.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <template>
  2. <div class="data-info">
  3. <el-card>
  4. <el-form :model="dataForm" label-width="120px">
  5. <el-form-item label="公式名称:">
  6. <el-input v-model="dataForm.name"></el-input>
  7. </el-form-item>
  8. <el-form-item label="公式:">
  9. <el-input
  10. type="textarea"
  11. v-model="dataForm.formula"
  12. @input="handleFormulaInput"
  13. ref="formulaInput"
  14. ></el-input>
  15. <div style="display: flex; justify-content: flex-end">
  16. <el-button style="margin-top: 10px" @click="InsertTableData"
  17. >插入表格数据</el-button
  18. >
  19. <el-button
  20. style="margin-top: 10px"
  21. type="primary"
  22. @click="InsertModule"
  23. >插入模块变量</el-button
  24. >
  25. </div>
  26. <div class="intro">
  27. 公式说明:
  28. <div>
  29. 格式一:[T][模块引用名][属性引用名] <span>*</span>其中
  30. [T]表示的是模块引用。
  31. </div>
  32. <div>目前仅支持+、-、*、/ 四种计算符合</div>
  33. <div>示例: [T][模块01][attr01]+[T][模块01][attr02]</div>
  34. <div>
  35. 格式二:[T][模块引用名][属性引用名]
  36. IF(判断条件,true值,false值)<span>*</span>其中
  37. [T]表示的是模块引用。
  38. </div>
  39. <div>
  40. 示例: [T][图文][测试1]+IF([T][图文][测试1]>30,[T][图文][测试2],11)
  41. </div>
  42. <div>
  43. 嵌套示例: [T][图文][测试1] + IF([T][图文][测试2] > 50,
  44. IF([T][图文][测试1] > 30, [T][图文][测试3], 20),
  45. IF([T][图文][测试3] > 40, 15, [T][图文][测试2]) )
  46. </div>
  47. </div>
  48. </el-form-item>
  49. <el-form-item label="保留小数点:">
  50. <el-input
  51. v-model.number="dataForm.point"
  52. type="number"
  53. min="0"
  54. max="4"
  55. :step="1"
  56. @input="validatePoint"
  57. ></el-input>
  58. </el-form-item>
  59. <el-form-item label="介绍:">
  60. <el-input type="textarea" v-model="dataForm.intro"></el-input>
  61. </el-form-item>
  62. <el-form-item label="公式状态:">
  63. <el-select
  64. v-model="dataForm.status"
  65. placeholder="请选择状态"
  66. size="large"
  67. style="width: 100%"
  68. >
  69. <el-option
  70. v-for="item in statusOptions"
  71. :key="item.value"
  72. :label="item.label"
  73. :value="item.value"
  74. />
  75. </el-select>
  76. </el-form-item>
  77. </el-form>
  78. </el-card>
  79. <div style="text-align: right; margin-top: 20px">
  80. <el-button type="warning" @click="btnSave">确认保存</el-button>
  81. </div>
  82. <el-dialog
  83. :visible.sync="variablesVisible"
  84. append-to-body
  85. width="300"
  86. custom-class="prod-verify"
  87. :title="title"
  88. :close-on-click-modal="false"
  89. @close="close"
  90. >
  91. <el-form :model="insertForm" :rules="insertRules" ref="insertRef">
  92. <el-form-item label="模块名称:">
  93. <el-select
  94. v-model="insertForm.moduleName"
  95. placeholder="请选择模块"
  96. size="large"
  97. style="width: 100%"
  98. @change="changeModule"
  99. >
  100. <el-option
  101. v-for="(item, index) in list"
  102. :key="`${item.id}-${index}`"
  103. :label="item.name"
  104. :value="item.attrs"
  105. />
  106. </el-select>
  107. </el-form-item>
  108. <el-form-item label="属性名称:" prop="Variable">
  109. <el-select
  110. v-model="insertForm.Variable"
  111. placeholder="请选择属性"
  112. size="large"
  113. style="width: 100%"
  114. >
  115. <el-option
  116. v-for="(item, index) in filteredAttrList"
  117. :key="`${item.id}-${index}`"
  118. :label="item.name"
  119. :value="item.id"
  120. />
  121. </el-select>
  122. </el-form-item>
  123. </el-form>
  124. <span slot="footer" class="dialog-footer">
  125. <el-button type="warning" @click="btnInster">确认插入</el-button>
  126. </span>
  127. </el-dialog>
  128. <el-dialog
  129. :visible.sync="tableDataVisible"
  130. append-to-body
  131. width="400"
  132. custom-class="prod-verify"
  133. title="插入表格数据"
  134. :close-on-click-modal="false"
  135. @close="close"
  136. >
  137. <div class="com-formual">
  138. <el-form>
  139. <el-form-item>
  140. <el-select
  141. v-model="tableCode"
  142. placeholder="请选择状态"
  143. @change="onChangeTab"
  144. size="large"
  145. style="width: 100%"
  146. >
  147. <el-option
  148. v-for="(item, index) in tableList"
  149. :key="item.id"
  150. :label="item.name"
  151. :value="index"
  152. />
  153. </el-select>
  154. </el-form-item>
  155. <el-form-item style="min-height: 500px" v-if="fileLoadStatus">
  156. <div
  157. id="luckysheets"
  158. ref="luckysheets"
  159. style="width: 100%; height: 500px"
  160. ></div>
  161. </el-form-item>
  162. </el-form>
  163. </div>
  164. </el-dialog>
  165. <el-dialog
  166. :visible.sync="showConfirm"
  167. title="数据确认"
  168. width="500"
  169. align-center
  170. :append-to-body="true"
  171. :close-on-click-modal="false"
  172. >
  173. <div>当前工作表:{{ position.sheet }}</div>
  174. <div>当前取值:{{ position.value }}</div>
  175. <template #footer>
  176. <div class="dialog-footer">
  177. <el-button @click="showConfirm = false">关闭</el-button>
  178. <el-button type="primary" @click="onConfirm">确认插入</el-button>
  179. </div>
  180. </template>
  181. </el-dialog>
  182. </div>
  183. </template>
  184. <script>
  185. import { createFormula, updateFormula, getFormulaInfo } from "@/api/formula";
  186. import { searchSourceData, deleteSourceData } from "@/api/sourceData";
  187. import LuckyExcel from "luckyexcel";
  188. export default {
  189. emits: ["onClose"],
  190. props: {
  191. id: {
  192. type: Number,
  193. default: 0,
  194. },
  195. list: {
  196. type: Array,
  197. default: [],
  198. },
  199. },
  200. watch: {
  201. id: {
  202. handler(newVal, oldVal) {
  203. if (newVal == null) return;
  204. if (newVal == 0) {
  205. this.resetForm();
  206. } else {
  207. // 添加条件以确保在id相同但需要重新获取数据时也能触发
  208. if (newVal !== oldVal || this.dataForm.id !== newVal) {
  209. this.getInfo(newVal);
  210. }
  211. }
  212. },
  213. immediate: true,
  214. },
  215. list: {
  216. handler(newValue, oldValue) {
  217. console.log("list changed:", newValue);
  218. },
  219. immediate: true,
  220. deep: true,
  221. },
  222. },
  223. data() {
  224. return {
  225. activeName: "base",
  226. currentCategory: [],
  227. allCategories: [],
  228. dataForm: {
  229. id: 0,
  230. name: "",
  231. formula: "",
  232. intro: "",
  233. status: 5,
  234. use_status: 5,
  235. params: "[]",
  236. point: 0,
  237. },
  238. statusOptions: [
  239. {
  240. value: "",
  241. label: "请选择状态",
  242. },
  243. {
  244. value: 5,
  245. label: "使用中",
  246. },
  247. {
  248. value: 6,
  249. label: "已停用",
  250. },
  251. ],
  252. variablesVisible: false,
  253. title: "",
  254. insertForm: {
  255. moduleName: "",
  256. Variable: "",
  257. },
  258. insertRules: {
  259. Variable: [
  260. { required: true, message: "请选择变量", trigger: "change" },
  261. ],
  262. },
  263. tableDataVisible: false,
  264. tableCode: "",
  265. tableList: [],
  266. showConfirm: false,
  267. fileLoadStatus: false,
  268. position: {
  269. tb: "",
  270. c: 0,
  271. r: 0,
  272. sheet: "",
  273. value: "",
  274. },
  275. attrList: [],
  276. };
  277. },
  278. mounted() {
  279. let _this = this;
  280. this.initTableList();
  281. },
  282. computed: {
  283. uniqueAttrList() {
  284. const uniqueNames = new Set();
  285. return this.attrList.filter(attr => {
  286. if (!uniqueNames.has(attr.name)) {
  287. uniqueNames.add(attr.name);
  288. return true;
  289. }
  290. return false;
  291. });
  292. },
  293. filteredAttrList() {
  294. return this.uniqueAttrList.filter(attr =>
  295. attr.type !== 'Directory'
  296. );
  297. }
  298. },
  299. methods: {
  300. validatePoint(value) {
  301. const intValue = parseInt(value);
  302. if (isNaN(intValue) || intValue < 0 || intValue > 4) {
  303. this.dataForm.point = "";
  304. } else {
  305. this.dataForm.point = intValue;
  306. }
  307. },
  308. /* 关闭 */
  309. close() {
  310. this.insertForm = {};
  311. },
  312. /* */
  313. handleFormulaInput(value) {
  314. // 更新 dataForm.formula 的值
  315. this.dataForm.formula = value;
  316. },
  317. resetForm() {
  318. this.dataForm = {
  319. id: 0,
  320. name: "",
  321. formula: "",
  322. intro: "",
  323. status: 5,
  324. use_status: 5,
  325. params: "[]",
  326. point: 0,
  327. };
  328. },
  329. btnSave(e) {
  330. let _this = this;
  331. const saveAction = _this.dataForm.id > 0 ? updateFormula : createFormula;
  332. saveAction(_this.dataForm)
  333. .then((res) => {
  334. _this.$message.success(
  335. _this.dataForm.id > 0 ? "公式更新成功" : "公式创建成功"
  336. );
  337. _this.$emit("onClose", true); // Pass a boolean to indicate successful save
  338. // 添加这行来强制重新获取数据
  339. _this.getInfo(_this.dataForm.id);
  340. _this.resetFormAfterSave();
  341. })
  342. .catch((error) => {
  343. console.error("保存失败:", error);
  344. _this.$message.error("保存失败,请重试");
  345. });
  346. },
  347. resetFormAfterSave() {
  348. this.dataForm = {
  349. id: 0,
  350. name: "",
  351. formula: "",
  352. intro: "",
  353. status: 5,
  354. use_status: 5,
  355. params: "[]",
  356. point: 0,
  357. };
  358. // If you have any other data that needs to be reset, do it here
  359. },
  360. //产品详情
  361. getInfo(id) {
  362. let _this = this;
  363. let par = {
  364. id: id,
  365. };
  366. getFormulaInfo(par).then((res) => {
  367. if (!res) return;
  368. if (res.status != 200) return;
  369. _this.dataForm = res.data;
  370. });
  371. },
  372. onChangeStatus(e) {
  373. this.dataForm.status = e;
  374. },
  375. //修改分类信息
  376. onChangeCategory(e) {
  377. let _this = this;
  378. _this.dataForm.categoryId = e;
  379. },
  380. /* 插入模块变量 */
  381. InsertModule() {
  382. this.variablesVisible = true;
  383. this.title = "插入模块变量";
  384. },
  385. extractChineseTemplates(content) {
  386. const templateRegex = /\{\{([\s\S]*?)\}\}/g; // 修改正则表达式以匹配多行内容
  387. const chineseRegex = /[\u4e00-\u9fa5]/;
  388. let match;
  389. const chineseTemplates = [];
  390. while ((match = templateRegex.exec(content)) !== null) {
  391. const trimmedMatch = match[1].trim();
  392. chineseTemplates.push(trimmedMatch);
  393. }
  394. return chineseTemplates;
  395. },
  396. processContent(val) {
  397. if (val && typeof val.content === "string") {
  398. const chineseTemplates = this.extractChineseTemplates(val.content);
  399. console.log("Extracted Chinese templates:", chineseTemplates);
  400. if (val.attrs && Array.isArray(val.attrs)) {
  401. this.attrList = val.attrs.filter((el) =>
  402. chineseTemplates.some((template) => template.includes(el.id))
  403. );
  404. }
  405. } else {
  406. this.attrList = [];
  407. }
  408. },
  409. /* 模块名称 */
  410. changeModule(value) {
  411. const selectedIndex = this.list.findIndex(
  412. (option) => option.attrs === value
  413. );
  414. this.processContent(this.list[selectedIndex]);
  415. //this.attrList = value; // 假设 attrs 属性包含了属性列表
  416. },
  417. /* 插入变量 */
  418. btnInster() {
  419. this.$refs.insertRef.validate((valid) => {
  420. if (valid) {
  421. const selectedModule = this.list.find(
  422. (module) => module.attrs === this.insertForm.moduleName
  423. );
  424. if (selectedModule) {
  425. const moduleName = selectedModule.name;
  426. const variableName = this.attrList.find(
  427. (attr) => attr.id === this.insertForm.Variable
  428. )?.name;
  429. if (variableName) {
  430. const insertText = `[T][${moduleName}][${variableName}]`;
  431. this.dataForm.formula += insertText;
  432. this.variablesVisible = false; // 关闭对话框
  433. this.$message.success("变量插入成功");
  434. } else {
  435. this.$message.error("无法找到选中的变量");
  436. }
  437. } else {
  438. this.$message.error("无法找到选中的模块");
  439. }
  440. } else {
  441. /* this.$message.error("请选择变量!"); */
  442. return false;
  443. }
  444. });
  445. },
  446. /* 插入表格数据 */
  447. InsertTableData() {
  448. this.tableDataVisible = true;
  449. },
  450. onConfirm(e) {
  451. this.showConfirm = false;
  452. const insertText = `[R][${this.position.tb}][${this.position.sheet}][${
  453. this.position.r + 1
  454. },${this.position.c + 1}]`;
  455. this.dataForm.formula += insertText;
  456. this.tableDataVisible = false;
  457. this.$message.success("表格数据插入成功");
  458. this.insertForm = {
  459. moduleName: {},
  460. Variable: "",
  461. };
  462. },
  463. onChangeTab(e) {
  464. let _this = this;
  465. let item = _this.tableList[e];
  466. _this.fileLoadStatus = true;
  467. item.sourceData = JSON.parse(item.source_data);
  468. console.log(item.sourceData.exportJson.sheets);
  469. _this.position.tb = item.code;
  470. _this.$nextTick(() => {
  471. luckysheet.destroy();
  472. luckysheet.create({
  473. container: "luckysheets",
  474. data: item.sourceData.exportJson.sheets,
  475. lang: "zh",
  476. showinfobar: false, // 是否显示顶部信息栏
  477. showstatisticBar: false, // 是否显示底部计数栏
  478. sheetBottomConfig: false, // sheet页下方的添加行按钮和回到顶部按钮配置
  479. allowEdit: false, // 是否允许前台编辑
  480. enableAddRow: false, // 是否允许增加行
  481. enableAddCol: false, // 是否允许增加列
  482. sheetFormulaBar: false, // 是否显示公式栏
  483. enableAddBackTop: false, // 返回头部按钮
  484. showsheetbar: true, // 是否显示底部sheet页按钮
  485. enableAddRow: false, //允许添加行
  486. showsheetbarConfig: {
  487. add: false,
  488. menu: false,
  489. },
  490. hook: {
  491. cellMousedown: function (cell, position, sheetFile, ctx) {
  492. _this.position.sheet = sheetFile.name;
  493. _this.position.r = position.r;
  494. _this.position.c = position.c;
  495. if (cell.v) {
  496. _this.position.value = cell.v;
  497. } else {
  498. _this.position.value = "";
  499. cell.ct.s.map((res) => {
  500. _this.position.value += res.v;
  501. });
  502. }
  503. _this.showConfirm = true;
  504. },
  505. },
  506. });
  507. });
  508. },
  509. initTableList() {
  510. let _this = this;
  511. searchSourceData({ page: 1, pageSize: 999, status: 5 }).then((res) => {
  512. if (res.status != 200) return;
  513. _this.tableList = res.data.dataList;
  514. });
  515. },
  516. },
  517. };
  518. </script>
  519. <style lang="scss">
  520. @import "./dataInfo.scss";
  521. </style>